mirror of
https://github.com/micropython/micropython.git
synced 2025-12-29 00:00:13 +01:00
Compare commits
792 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5653e3c72f | ||
|
|
a722ed532f | ||
|
|
b528e9a428 | ||
|
|
b2611d6be3 | ||
|
|
044f96c330 | ||
|
|
a1a8f01799 | ||
|
|
ef1bbada96 | ||
|
|
e5a6a26330 | ||
|
|
36ec5c8f27 | ||
|
|
e343bea6e7 | ||
|
|
cc7e48fdc8 | ||
|
|
4a72294d7d | ||
|
|
5d0d61586c | ||
|
|
98458a46ec | ||
|
|
343b4189b0 | ||
|
|
8d1c236a1f | ||
|
|
1551309575 | ||
|
|
ea00151ffa | ||
|
|
d7e168428b | ||
|
|
64dc925c4a | ||
|
|
ec72db8a39 | ||
|
|
26f00ff154 | ||
|
|
eac22e29a5 | ||
|
|
c3f70c603e | ||
|
|
bae7798f1e | ||
|
|
b0f23786da | ||
|
|
52c19875a4 | ||
|
|
54ea10a76a | ||
|
|
e1f495a4bd | ||
|
|
3c84197f17 | ||
|
|
3d96201165 | ||
|
|
3f9c45efd1 | ||
|
|
714a59ab64 | ||
|
|
f5750e88c5 | ||
|
|
86d210951f | ||
|
|
5efd6508ec | ||
|
|
093a8f5fa2 | ||
|
|
d377c83794 | ||
|
|
71ff0b549d | ||
|
|
b315d76b6b | ||
|
|
0748143a4c | ||
|
|
75aa7befec | ||
|
|
b7024f0f64 | ||
|
|
f397e1fdf0 | ||
|
|
c15ebf7c8c | ||
|
|
45a8cc8f0b | ||
|
|
514b82900c | ||
|
|
076b80467b | ||
|
|
afc5063539 | ||
|
|
eae819c0ed | ||
|
|
e81116d07d | ||
|
|
16a584d7cf | ||
|
|
65574f817a | ||
|
|
ea6a958393 | ||
|
|
44bf8e1f2b | ||
|
|
ca7af9a778 | ||
|
|
43384ad7e7 | ||
|
|
2d9440e2d1 | ||
|
|
c2dd494bd9 | ||
|
|
25f44c19f1 | ||
|
|
cf96be60dc | ||
|
|
05aebb9206 | ||
|
|
492c612f9d | ||
|
|
7327966da7 | ||
|
|
18f12caafc | ||
|
|
1e9093f8cb | ||
|
|
1328833663 | ||
|
|
ea426dd9ef | ||
|
|
e202b6f586 | ||
|
|
ed559de063 | ||
|
|
ffa30898cc | ||
|
|
425150040c | ||
|
|
b14abab9cd | ||
|
|
ffe807f349 | ||
|
|
efa206d955 | ||
|
|
97f3797b82 | ||
|
|
cdec7ba30e | ||
|
|
ebb8413178 | ||
|
|
c305ae3243 | ||
|
|
f4aebafe7a | ||
|
|
b9c4783273 | ||
|
|
adccafb42a | ||
|
|
1b44987d0c | ||
|
|
64b1d5f878 | ||
|
|
5d9025a76e | ||
|
|
d02f6a9956 | ||
|
|
ef23399e32 | ||
|
|
1731868ae7 | ||
|
|
531c206e8b | ||
|
|
46a6592f9a | ||
|
|
e4af712125 | ||
|
|
67f3edc10a | ||
|
|
9af73bda33 | ||
|
|
c1e94b77a4 | ||
|
|
5d06a74303 | ||
|
|
1e7a801e2d | ||
|
|
7bbce4e213 | ||
|
|
b470f59892 | ||
|
|
d291007fea | ||
|
|
49bf7617d0 | ||
|
|
7318949c46 | ||
|
|
0d32f1aeb3 | ||
|
|
5e1ccddc82 | ||
|
|
91359c8690 | ||
|
|
de9cd00b39 | ||
|
|
bbd0d27a25 | ||
|
|
56a514c193 | ||
|
|
0c59c30fde | ||
|
|
724b82559d | ||
|
|
87e426c7c7 | ||
|
|
48d81c6900 | ||
|
|
a770ba147e | ||
|
|
d89cafd5c3 | ||
|
|
7f1da0a03b | ||
|
|
979ab4e126 | ||
|
|
f254cfd3c4 | ||
|
|
29b5879613 | ||
|
|
1b02565316 | ||
|
|
7081ea4119 | ||
|
|
a5b3c7e7f9 | ||
|
|
0caac94b98 | ||
|
|
c16e7eae5e | ||
|
|
95fe7a40b3 | ||
|
|
403c93053e | ||
|
|
ee7ad7e8be | ||
|
|
e8f2db7da3 | ||
|
|
e83f140463 | ||
|
|
9112b0b62b | ||
|
|
0f408bc1ff | ||
|
|
8001918a89 | ||
|
|
3dd04dee3e | ||
|
|
e9fbc555fc | ||
|
|
517f347f6f | ||
|
|
d9047d3c8a | ||
|
|
d22762017e | ||
|
|
a3c61004c2 | ||
|
|
aee13ef3f2 | ||
|
|
9d787de2a1 | ||
|
|
93ee6603b1 | ||
|
|
155fdc74d5 | ||
|
|
e920bab976 | ||
|
|
dd53b12193 | ||
|
|
a7fd786a1f | ||
|
|
3a4ebf5768 | ||
|
|
f76b1bfa9f | ||
|
|
ad297a1950 | ||
|
|
45a6156dfd | ||
|
|
8e5aced1fd | ||
|
|
fcac4b07f1 | ||
|
|
81316fa411 | ||
|
|
c8746e1e72 | ||
|
|
c2713592bc | ||
|
|
adf3cb5081 | ||
|
|
5e393007b9 | ||
|
|
898d4c1217 | ||
|
|
ad166857bc | ||
|
|
1b6d94bccd | ||
|
|
1eb3c66e91 | ||
|
|
d9c839742f | ||
|
|
db5a4e8f3c | ||
|
|
6901649f54 | ||
|
|
44cb2ff7ab | ||
|
|
821863751f | ||
|
|
e1c6ed634f | ||
|
|
b9741cd8f8 | ||
|
|
d9677f4098 | ||
|
|
080a78b15e | ||
|
|
4c7d799b82 | ||
|
|
aaab6a9921 | ||
|
|
27a503f632 | ||
|
|
4fc607a1d7 | ||
|
|
042d5f24d6 | ||
|
|
374ed317c5 | ||
|
|
0db3a41f02 | ||
|
|
fcd10882bd | ||
|
|
e44b236ce2 | ||
|
|
4463d8a910 | ||
|
|
1779a62085 | ||
|
|
46e59c52af | ||
|
|
ec22d1739d | ||
|
|
bd476acd41 | ||
|
|
e50cb73b7a | ||
|
|
cb53226b0c | ||
|
|
2d329c4a56 | ||
|
|
ebc8d730f1 | ||
|
|
304cfda8c4 | ||
|
|
6194336d81 | ||
|
|
f7545b200e | ||
|
|
b7df3e541a | ||
|
|
08bd7d1d31 | ||
|
|
a081b49d55 | ||
|
|
81e171b7bb | ||
|
|
eb09336e99 | ||
|
|
225e22b287 | ||
|
|
8b8242954e | ||
|
|
c19a395cac | ||
|
|
390ce86a30 | ||
|
|
52dfad0879 | ||
|
|
e72353cc48 | ||
|
|
87215a0f04 | ||
|
|
295266178c | ||
|
|
a6de451a13 | ||
|
|
63e82dcdfe | ||
|
|
029f215ead | ||
|
|
0d75b0d962 | ||
|
|
50a2966913 | ||
|
|
139b891d6d | ||
|
|
612599587b | ||
|
|
21e1703d37 | ||
|
|
dbc09d03f6 | ||
|
|
4c3c515bd1 | ||
|
|
e6cf5fb2cc | ||
|
|
a4f96c8c2a | ||
|
|
a31a3a9fd5 | ||
|
|
f8b71aabb4 | ||
|
|
49dcc253e3 | ||
|
|
652ca2017d | ||
|
|
3053748987 | ||
|
|
5d2279bec1 | ||
|
|
8b74048d2a | ||
|
|
4c905616f0 | ||
|
|
37333cb00a | ||
|
|
0bc99b4836 | ||
|
|
07e83573c8 | ||
|
|
ced240e72a | ||
|
|
946f8dd46f | ||
|
|
96c3911a0a | ||
|
|
c81247f1ab | ||
|
|
bc4ea69795 | ||
|
|
b983cfaf41 | ||
|
|
63a5df3cb4 | ||
|
|
a3320e7811 | ||
|
|
2eff9c29a1 | ||
|
|
1b41cacac7 | ||
|
|
037e6912c6 | ||
|
|
7e820792da | ||
|
|
1f43d49f9e | ||
|
|
d70f87aaa2 | ||
|
|
21d82421cd | ||
|
|
e30ca0e102 | ||
|
|
0d56c65d3e | ||
|
|
5362bcc487 | ||
|
|
f14e9187ac | ||
|
|
87dfc76570 | ||
|
|
8f5bc3ffc0 | ||
|
|
c28fed6b64 | ||
|
|
00d6f99cf1 | ||
|
|
e81a5353cb | ||
|
|
9a82b67f39 | ||
|
|
702928915c | ||
|
|
b188d6e9db | ||
|
|
5e9057210a | ||
|
|
e01e214259 | ||
|
|
87f18c08c9 | ||
|
|
c5621529c9 | ||
|
|
4d9dce7759 | ||
|
|
13400e1375 | ||
|
|
8fa0733647 | ||
|
|
7604de3fc2 | ||
|
|
dc1ac5dc3a | ||
|
|
63ca7a211a | ||
|
|
0280b2c1b1 | ||
|
|
fa833f96df | ||
|
|
7928b3e347 | ||
|
|
6a8f6c119c | ||
|
|
e2b4822189 | ||
|
|
4f7c5fa647 | ||
|
|
c79ff9930a | ||
|
|
a9fb88e1dc | ||
|
|
e8b435d1f8 | ||
|
|
c1fa33b493 | ||
|
|
4f5c4fdd98 | ||
|
|
32e98257e2 | ||
|
|
85ae17c993 | ||
|
|
5bdf1650de | ||
|
|
66d955c218 | ||
|
|
e5ef15a9d7 | ||
|
|
511c083811 | ||
|
|
6b239c271c | ||
|
|
6810f2c134 | ||
|
|
64db4080ce | ||
|
|
30bca45e1a | ||
|
|
9b525134d1 | ||
|
|
ed9c93f0f1 | ||
|
|
b0cbfb0492 | ||
|
|
3f8bb80eb2 | ||
|
|
7602dc5f32 | ||
|
|
659b06b250 | ||
|
|
0400fa45ba | ||
|
|
a0b2c6ad32 | ||
|
|
79d996a57b | ||
|
|
a392b3aa75 | ||
|
|
aed3b5b7ba | ||
|
|
c3d96d387c | ||
|
|
bf318801d2 | ||
|
|
8212773adb | ||
|
|
00a9590e3a | ||
|
|
59a1201da9 | ||
|
|
99e5badeb1 | ||
|
|
30cfdc29ed | ||
|
|
0cbc07227c | ||
|
|
3c0da6a359 | ||
|
|
1375c52772 | ||
|
|
74fb5d6932 | ||
|
|
c4e58eaa98 | ||
|
|
e6da6a720f | ||
|
|
679c0c4c83 | ||
|
|
0f3388de1e | ||
|
|
5a1d63fc14 | ||
|
|
29f3f84fbd | ||
|
|
11957840e8 | ||
|
|
3e5e4f95b2 | ||
|
|
52df2f889e | ||
|
|
2bf96612d2 | ||
|
|
e3626b484c | ||
|
|
fcda6a2a78 | ||
|
|
bdf33bc136 | ||
|
|
5630778f0f | ||
|
|
933198c55f | ||
|
|
1cc168d487 | ||
|
|
61d74fdef8 | ||
|
|
bc4441afa7 | ||
|
|
8ebd53afc9 | ||
|
|
8f068e84ee | ||
|
|
5c3d75c937 | ||
|
|
e84e3e7c10 | ||
|
|
fa3a108ed7 | ||
|
|
8bc3fc20fe | ||
|
|
3ccdbf792c | ||
|
|
50e8e28f96 | ||
|
|
f59465d763 | ||
|
|
919fc2dc47 | ||
|
|
688cc79294 | ||
|
|
13f7a7b86b | ||
|
|
9b345a9e48 | ||
|
|
3272afe57f | ||
|
|
0b9ed55026 | ||
|
|
7bb0f7b0f6 | ||
|
|
561844f3ba | ||
|
|
ca973bd308 | ||
|
|
cd527bb324 | ||
|
|
828df54bfe | ||
|
|
94aeba0427 | ||
|
|
f9b6b37cf6 | ||
|
|
e5f06559e6 | ||
|
|
10bde6933e | ||
|
|
5fae914326 | ||
|
|
2ec70dc812 | ||
|
|
ffb04a5845 | ||
|
|
a6c9060d81 | ||
|
|
b97c17e125 | ||
|
|
eddcf0a5de | ||
|
|
805f7ea2f2 | ||
|
|
8679d9e6a6 | ||
|
|
7ffc959c00 | ||
|
|
3679ee9b52 | ||
|
|
e377f3cb40 | ||
|
|
d60ad5cf53 | ||
|
|
153665f159 | ||
|
|
7219a18d17 | ||
|
|
796b720dbc | ||
|
|
be6a765c69 | ||
|
|
8908e505ce | ||
|
|
e429daa572 | ||
|
|
76146b3d9a | ||
|
|
1ba4db5685 | ||
|
|
64c6bdb8ee | ||
|
|
369233105b | ||
|
|
d86cac4b82 | ||
|
|
c62679bdaa | ||
|
|
6a2c6098f4 | ||
|
|
3cc87b1e2a | ||
|
|
6a87084019 | ||
|
|
99ed0f25cb | ||
|
|
6ed5583f8c | ||
|
|
e381efed4a | ||
|
|
aee6483536 | ||
|
|
938c693948 | ||
|
|
cc0cc67815 | ||
|
|
b83ac44e82 | ||
|
|
b0feef7a57 | ||
|
|
c28f9df63a | ||
|
|
b9a88683a4 | ||
|
|
964fb2450e | ||
|
|
8a49905a2f | ||
|
|
52aa532050 | ||
|
|
fbca4f94b3 | ||
|
|
38a9359339 | ||
|
|
67b6d9d499 | ||
|
|
a3519332b6 | ||
|
|
3cdccb9b14 | ||
|
|
6832cbd69d | ||
|
|
c38ea32810 | ||
|
|
73b72799f3 | ||
|
|
f00ecdb54d | ||
|
|
67c91df7e8 | ||
|
|
760ed4629f | ||
|
|
d5cf8c5753 | ||
|
|
ca008bfd2d | ||
|
|
f7aa692093 | ||
|
|
984a867341 | ||
|
|
f1b2b1b600 | ||
|
|
2550d7dfd2 | ||
|
|
b78144c64d | ||
|
|
e6af94d13b | ||
|
|
266e4acdc2 | ||
|
|
25c6fc731b | ||
|
|
5076e5c339 | ||
|
|
bc5b896f24 | ||
|
|
bdb0d2d0bc | ||
|
|
5694201930 | ||
|
|
06e7032906 | ||
|
|
cb20d999bc | ||
|
|
b6c22c42ab | ||
|
|
a4dbb4230a | ||
|
|
197a5724d8 | ||
|
|
479b961d39 | ||
|
|
1b76614d41 | ||
|
|
979e9a45d8 | ||
|
|
3730090d8f | ||
|
|
f64e806f50 | ||
|
|
571e6f26db | ||
|
|
4ebdb1f2b2 | ||
|
|
5d0735b93a | ||
|
|
3967ca7390 | ||
|
|
b440307b4a | ||
|
|
3f251efb9b | ||
|
|
84679e0c06 | ||
|
|
17ba6ef5fa | ||
|
|
204222653e | ||
|
|
9514d847fe | ||
|
|
462748de0c | ||
|
|
e7e0d91be8 | ||
|
|
6566e3f6a8 | ||
|
|
20d0271863 | ||
|
|
542f05d228 | ||
|
|
b4cc68e4a4 | ||
|
|
d49d81b167 | ||
|
|
cd9b14bb11 | ||
|
|
5c93d0b916 | ||
|
|
628799cd36 | ||
|
|
f12047f66d | ||
|
|
50ddaafa6a | ||
|
|
4d45f286eb | ||
|
|
a0b2f48c2f | ||
|
|
c8d31585a0 | ||
|
|
1e3a7c4ac5 | ||
|
|
48feb8ac6e | ||
|
|
57226a2b7f | ||
|
|
ad3724e0bc | ||
|
|
7d0d7215d2 | ||
|
|
6caca3259f | ||
|
|
2750a7b38e | ||
|
|
a3edeb9ea5 | ||
|
|
e9404e5f5f | ||
|
|
453c2e8f55 | ||
|
|
799ccdc789 | ||
|
|
06234a6115 | ||
|
|
36f97f19b4 | ||
|
|
f059563507 | ||
|
|
a97284423e | ||
|
|
824f5c5a32 | ||
|
|
ed878275b0 | ||
|
|
34d0b3f85c | ||
|
|
6a4c6fc023 | ||
|
|
b0a15aa735 | ||
|
|
8298251215 | ||
|
|
e42186d356 | ||
|
|
f2f8ae110b | ||
|
|
11ab807d76 | ||
|
|
e93c1ca5da | ||
|
|
f17f3314d0 | ||
|
|
1a01ed0d2a | ||
|
|
b6a544b917 | ||
|
|
06ee5e947f | ||
|
|
998578a2b8 | ||
|
|
cdbeee0c50 | ||
|
|
4021b1e1b8 | ||
|
|
af8d791bd0 | ||
|
|
11fc6553e8 | ||
|
|
31101d91ce | ||
|
|
deaa57acf3 | ||
|
|
db4e009217 | ||
|
|
f274561e16 | ||
|
|
d02f3a57f4 | ||
|
|
eaef6b5324 | ||
|
|
9e1dec1818 | ||
|
|
39968aaaff | ||
|
|
6dff3df501 | ||
|
|
8bb7d958f1 | ||
|
|
df3e5d2b2f | ||
|
|
48874942f0 | ||
|
|
5e22afce41 | ||
|
|
e49153fb98 | ||
|
|
7f0e563de3 | ||
|
|
7dc2345715 | ||
|
|
93c76d2b06 | ||
|
|
1b76f88e7a | ||
|
|
aa7828f822 | ||
|
|
7e3b21ec54 | ||
|
|
b3a65791b1 | ||
|
|
ac70119779 | ||
|
|
a181340ad8 | ||
|
|
5a699a7017 | ||
|
|
244b02f744 | ||
|
|
cbc0bf6fec | ||
|
|
2ea52cb045 | ||
|
|
7df9f313c6 | ||
|
|
9ad5032164 | ||
|
|
9d9efc0c5a | ||
|
|
cff9f02cd7 | ||
|
|
fa5ac678fc | ||
|
|
3dabaae47d | ||
|
|
d22a04d9c4 | ||
|
|
49e140488d | ||
|
|
3b3612c65b | ||
|
|
dc43508cc2 | ||
|
|
016dba0e98 | ||
|
|
503089ea9d | ||
|
|
23a568240d | ||
|
|
a2bfcbe029 | ||
|
|
e3d29996b3 | ||
|
|
75af908c0e | ||
|
|
06d0083468 | ||
|
|
620c4c32bf | ||
|
|
3a0a771730 | ||
|
|
0363e1d7b5 | ||
|
|
00c1fc6d77 | ||
|
|
82af4d6749 | ||
|
|
dffa383b06 | ||
|
|
9fdba0e09c | ||
|
|
056da75a8a | ||
|
|
0bb3c7d3b7 | ||
|
|
c08f50bcf7 | ||
|
|
7f19b1c3eb | ||
|
|
b89ac9db78 | ||
|
|
b1537a5752 | ||
|
|
bcf60b43ee | ||
|
|
7a9c183c20 | ||
|
|
cecf6bee97 | ||
|
|
161e9f4115 | ||
|
|
52784bf595 | ||
|
|
addd1d3db1 | ||
|
|
99d62c4def | ||
|
|
8f3cf6e6a8 | ||
|
|
eb239b8398 | ||
|
|
03de5a13cf | ||
|
|
cd20027f56 | ||
|
|
1f433c719b | ||
|
|
bd925b59c3 | ||
|
|
b0eb0d6153 | ||
|
|
b932b2dd1f | ||
|
|
9f1e395c16 | ||
|
|
bd87375202 | ||
|
|
5deedd6685 | ||
|
|
d4a5ca5056 | ||
|
|
077dbf4a86 | ||
|
|
d434ce3fca | ||
|
|
a22a67661a | ||
|
|
5bb28c7f10 | ||
|
|
a0d97fe408 | ||
|
|
8de270b4fc | ||
|
|
eca1408f16 | ||
|
|
3be4f886ce | ||
|
|
9f72a14920 | ||
|
|
b04d4a5b13 | ||
|
|
fa6f774b2c | ||
|
|
6aea34ad89 | ||
|
|
17b4509564 | ||
|
|
3c582bc7cb | ||
|
|
216a711cd4 | ||
|
|
6cf2a3966e | ||
|
|
0d10517a45 | ||
|
|
d5495966ce | ||
|
|
3dea8c9e92 | ||
|
|
6ab2c5e6cc | ||
|
|
53bfcc9e84 | ||
|
|
219245e10f | ||
|
|
7165fbd8f4 | ||
|
|
b32c01b748 | ||
|
|
443cc0114d | ||
|
|
2c7716fed0 | ||
|
|
dd4135aeaf | ||
|
|
0c595fa094 | ||
|
|
c71edaed73 | ||
|
|
88ca7ff565 | ||
|
|
7385b018ed | ||
|
|
897129a7ff | ||
|
|
290daa15d9 | ||
|
|
4fb72fe624 | ||
|
|
670376c5cb | ||
|
|
dcf14c1b18 | ||
|
|
791b65f4b2 | ||
|
|
f65e4f0b8f | ||
|
|
71fec076dc | ||
|
|
38b54b65d4 | ||
|
|
3f0c1c2452 | ||
|
|
f040685b0c | ||
|
|
67d52d8cb9 | ||
|
|
d46de80162 | ||
|
|
7b901d6fb7 | ||
|
|
d8a4d9d67c | ||
|
|
4c63986101 | ||
|
|
9cc8ec843e | ||
|
|
6d310a5552 | ||
|
|
eeb9d99333 | ||
|
|
7df9291b6c | ||
|
|
e97df97600 | ||
|
|
46ab042230 | ||
|
|
ec078af985 | ||
|
|
1f69b16d3f | ||
|
|
9310dad15d | ||
|
|
c4a69c75a5 | ||
|
|
6c79980b0e | ||
|
|
79ec869f95 | ||
|
|
c528489eee | ||
|
|
080e4d44f3 | ||
|
|
5f0ecb72c2 | ||
|
|
7f5a541b84 | ||
|
|
b84e1231c9 | ||
|
|
9ea2882317 | ||
|
|
93c4a6a3f7 | ||
|
|
b0a46900de | ||
|
|
7ea3fa2641 | ||
|
|
21c719bd0a | ||
|
|
34e0198436 | ||
|
|
cc7c311b5e | ||
|
|
3f5fe6269e | ||
|
|
bb954d80a4 | ||
|
|
fbddea929d | ||
|
|
60592fd23c | ||
|
|
b85bcd671c | ||
|
|
e60835bac5 | ||
|
|
4874bde104 | ||
|
|
8dd5960ac0 | ||
|
|
5da0d29d3c | ||
|
|
adaf0d865c | ||
|
|
a5624bf381 | ||
|
|
4b3f1d712b | ||
|
|
3fe047f08f | ||
|
|
4ab3eef8d7 | ||
|
|
a2391b5a74 | ||
|
|
5bf1b4e9d9 | ||
|
|
d08c9d342f | ||
|
|
f28efa1971 | ||
|
|
8ae885a0c6 | ||
|
|
ee324c501e | ||
|
|
b9672bcbe8 | ||
|
|
2b7c4a1878 | ||
|
|
67a4813601 | ||
|
|
f84b341618 | ||
|
|
3fea1f014c | ||
|
|
0fd3d8d19f | ||
|
|
081c0648ec | ||
|
|
dd0e6ddfeb | ||
|
|
d14d4cdb8b | ||
|
|
a50b26e4b0 | ||
|
|
b236b1974b | ||
|
|
2f02960607 | ||
|
|
1ba516f475 | ||
|
|
06a1194300 | ||
|
|
d89de18f40 | ||
|
|
f3b19ef634 | ||
|
|
3611dcc260 | ||
|
|
763e04bba5 | ||
|
|
f3b5480be7 | ||
|
|
dab0f316d2 | ||
|
|
742d8bdbe4 | ||
|
|
b4be5a8f34 | ||
|
|
4a9542c0c0 | ||
|
|
9103cbe366 | ||
|
|
b88bf6c76b | ||
|
|
69768c97c0 | ||
|
|
e4d6a10dc9 | ||
|
|
2b882e9aca | ||
|
|
ef47a67cf4 | ||
|
|
9526e24234 | ||
|
|
e2ac8bb3f1 | ||
|
|
cac8dc3414 | ||
|
|
778729c597 | ||
|
|
b4df3e74e1 | ||
|
|
20da9064d7 | ||
|
|
dba40afa70 | ||
|
|
7ddd1a58f6 | ||
|
|
1708fe3cc7 | ||
|
|
61e2dfd97d | ||
|
|
1bc5cb4312 | ||
|
|
fedab995ee | ||
|
|
2d8740a4d1 | ||
|
|
47899a1ab8 | ||
|
|
8c6856d2e7 | ||
|
|
015774a04f | ||
|
|
4a33677c97 | ||
|
|
76c366df56 | ||
|
|
f7c4611523 | ||
|
|
fafd587514 | ||
|
|
a6864a13c7 | ||
|
|
c51c883cc8 | ||
|
|
41ec22632d | ||
|
|
b6bdf18deb | ||
|
|
b4790afdaf | ||
|
|
58f3861358 | ||
|
|
5f3bda422a | ||
|
|
f127bef3e4 | ||
|
|
f98bb2ddcb | ||
|
|
ce1c786297 | ||
|
|
49406b0ac6 | ||
|
|
9b64d1966b | ||
|
|
3be8b688c0 | ||
|
|
5863e15a23 | ||
|
|
0823c1baf8 | ||
|
|
9c04ef2a67 | ||
|
|
1f61fe07a2 | ||
|
|
bae62d9abe | ||
|
|
76dcaddc0f | ||
|
|
efc904c41d | ||
|
|
5c3a2f162e | ||
|
|
d1a366fdd4 | ||
|
|
c777b6950e | ||
|
|
0f8b1ba8a2 | ||
|
|
f2da6467a9 | ||
|
|
57c92d90b0 | ||
|
|
13c5a228c9 | ||
|
|
59a9509703 | ||
|
|
8e9b98e974 | ||
|
|
9fba618356 | ||
|
|
ed0a06a93f | ||
|
|
263aaa7030 | ||
|
|
8f8f699eb7 | ||
|
|
f4ee9f8853 | ||
|
|
581a59a456 | ||
|
|
531217a06b | ||
|
|
fea7fe45ea | ||
|
|
26295e04ff | ||
|
|
fe3cc5bb53 | ||
|
|
3b5affa0d1 | ||
|
|
24df30c133 | ||
|
|
fc73c9b4b2 | ||
|
|
5ffe1d8dc0 | ||
|
|
d29ca28288 | ||
|
|
b0e2106fb8 | ||
|
|
891479e62a | ||
|
|
9897bcaa73 | ||
|
|
a589fa3e0b | ||
|
|
d09b6b9aa1 | ||
|
|
78bc31e294 | ||
|
|
5af6184e72 | ||
|
|
c428367543 | ||
|
|
39799f7564 | ||
|
|
6562076454 | ||
|
|
5a5449d4eb | ||
|
|
253e1a6f67 | ||
|
|
d2d9dfcd40 | ||
|
|
c6983e3ce0 | ||
|
|
f2a21a2489 | ||
|
|
d076fae219 | ||
|
|
8e7dfea803 | ||
|
|
49dd532180 | ||
|
|
64c5a9435c | ||
|
|
567e7fcd12 | ||
|
|
244332df9f | ||
|
|
a6fc90f92a | ||
|
|
ed4ce196ed | ||
|
|
ff1c2b03a9 | ||
|
|
bb19e7b94b | ||
|
|
f003310dee | ||
|
|
ed6a1ada24 | ||
|
|
d2cc7c720b | ||
|
|
095e43a9a5 | ||
|
|
f6a8e84a25 | ||
|
|
675d1c9c60 | ||
|
|
41fceae559 | ||
|
|
b359cf2911 | ||
|
|
d5f42c9daf | ||
|
|
3c82d1d34b | ||
|
|
2196799051 | ||
|
|
1a0d3fd632 | ||
|
|
4aaa5adf9f | ||
|
|
9cf2949356 | ||
|
|
0be4a7712d | ||
|
|
c4a8004933 | ||
|
|
83e0ebabb4 | ||
|
|
8c50f93a41 | ||
|
|
9e1b61dedd | ||
|
|
af9889f99a | ||
|
|
dfb8144037 | ||
|
|
4e36dd570b | ||
|
|
5e01fb01b3 | ||
|
|
72ae3c72c7 | ||
|
|
8a15e0b1c7 | ||
|
|
b203c1774e | ||
|
|
2146cdab5e |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,6 +32,7 @@ tests/*.out
|
||||
# Python cache files
|
||||
######################
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Customized Makefile/project overrides
|
||||
######################
|
||||
|
||||
19
.travis.yml
19
.travis.yml
@@ -3,6 +3,9 @@ dist: trusty
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
cache:
|
||||
directories:
|
||||
- "${HOME}/persist"
|
||||
|
||||
before_script:
|
||||
# Extra CPython versions
|
||||
@@ -12,7 +15,7 @@ before_script:
|
||||
- sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded
|
||||
- sudo dpkg --add-architecture i386
|
||||
- sudo apt-get update -qq || true
|
||||
- sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32
|
||||
- sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system gcc-mingw-w64
|
||||
- sudo apt-get install -y --force-yes gcc-arm-none-eabi
|
||||
# For teensy build
|
||||
- sudo apt-get install realpath
|
||||
@@ -23,7 +26,13 @@ before_script:
|
||||
- python3 --version
|
||||
|
||||
script:
|
||||
- make -C minimal test
|
||||
- make -C mpy-cross
|
||||
- make -C minimal CROSS=1 build/firmware.bin
|
||||
- ls -l minimal/build/firmware.bin
|
||||
- tools/check_code_size.sh
|
||||
- mkdir -p ${HOME}/persist
|
||||
# Save new firmware for reference, but only if building a main branch, not a pull request
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp minimal/build/firmware.bin ${HOME}/persist/; fi'
|
||||
- make -C unix deplibs
|
||||
- make -C unix
|
||||
- make -C unix nanbox
|
||||
@@ -31,11 +40,12 @@ script:
|
||||
- make -C qemu-arm test
|
||||
- make -C stmhal
|
||||
- make -C stmhal -B MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1
|
||||
- make -C stmhal BOARD=STM32F4DISC
|
||||
- make -C stmhal BOARD=STM32F7DISC
|
||||
- make -C stmhal BOARD=STM32L476DISC
|
||||
- make -C teensy
|
||||
- make -C cc3200 BTARGET=application BTYPE=release
|
||||
- make -C cc3200 BTARGET=bootloader BTYPE=release
|
||||
- make -C windows CROSS_COMPILE=i586-mingw32msvc-
|
||||
- make -C windows CROSS_COMPILE=i686-w64-mingw32-
|
||||
|
||||
# run tests without coverage info
|
||||
#- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests)
|
||||
@@ -46,6 +56,7 @@ script:
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests)
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests -d thread)
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --emit native)
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --via-mpy -d basics float)
|
||||
|
||||
after_success:
|
||||
- (cd unix && coveralls --root .. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod)
|
||||
|
||||
@@ -1448,7 +1448,7 @@ indicating that they also supported the first campaign.
|
||||
* 902 B Stevens
|
||||
903 Cptnslick, US
|
||||
904 janlj@me.com
|
||||
905 São Caetano do Sul, SP, Brazil
|
||||
905 Fabricio Biazzotto
|
||||
906 Lenz Hirsch
|
||||
907 SerSher, RU
|
||||
908 Florian, DE
|
||||
|
||||
17
README.md
17
README.md
@@ -1,12 +1,8 @@
|
||||
[![Build Status][travis-img]][travis-repo] [![Coverage Status][coveralls-img]][coveralls-repo] [![Issue Stats][istats-pr-img]][istats-pr-repo] [![Issue Stats][istats-issue-img]][istats-issue-repo]
|
||||
[![Build Status][travis-img]][travis-repo] [![Coverage Status][coveralls-img]][coveralls-repo]
|
||||
[travis-img]: https://travis-ci.org/micropython/micropython.png?branch=master
|
||||
[travis-repo]: https://travis-ci.org/micropython/micropython
|
||||
[coveralls-img]: https://coveralls.io/repos/micropython/micropython/badge.png?branch=master
|
||||
[coveralls-repo]: https://coveralls.io/r/micropython/micropython?branch=master
|
||||
[istats-pr-img]: http://issuestats.com/github/micropython/micropython/badge/pr
|
||||
[istats-pr-repo]: http://issuestats.com/github/micropython/micropython
|
||||
[istats-issue-img]: http://issuestats.com/github/micropython/micropython/badge/issue
|
||||
[istats-issue-repo]: http://issuestats.com/github/micropython/micropython
|
||||
|
||||
The MicroPython project
|
||||
=======================
|
||||
@@ -26,18 +22,19 @@ MicroPython implements the entire Python 3.4 syntax (including exceptions,
|
||||
The following core datatypes are provided: str (including basic Unicode
|
||||
support), bytes, bytearray, tuple, list, dict, set, frozenset, array.array,
|
||||
collections.namedtuple, classes and instances. Builtin modules include sys,
|
||||
time, and struct. Note that only subset of Python 3.4 functionality
|
||||
time, and struct, etc. Select ports have support for _thread module
|
||||
(multithreading). Note that only subset of Python 3.4 functionality
|
||||
implemented for the data types and modules.
|
||||
|
||||
See the repository www.github.com/micropython/pyboard for the Micro
|
||||
Python board, the officially supported reference electronic circuit board.
|
||||
See the repository www.github.com/micropython/pyboard for the MicroPython
|
||||
board (PyBoard), the officially supported reference electronic circuit board.
|
||||
|
||||
Major components in this repository:
|
||||
- py/ -- the core Python implementation, including compiler, runtime, and
|
||||
core library.
|
||||
- unix/ -- a version of MicroPython that runs on Unix.
|
||||
- stmhal/ -- a version of MicroPython that runs on the MicroPython board
|
||||
with an STM32F405RG (using ST's Cube HAL drivers).
|
||||
- stmhal/ -- a version of MicroPython that runs on the PyBoard and similar
|
||||
STM32 boards (using ST's Cube HAL drivers).
|
||||
- minimal/ -- a minimal MicroPython port. Start with this if you want
|
||||
to port MicroPython to another microcontroller.
|
||||
- tests/ -- test framework and test scripts.
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#define MICROPY_CPYTHON_COMPAT (0)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
@@ -54,15 +55,12 @@
|
||||
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef uint32_t mp_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
// dummy print
|
||||
#define MP_PLAT_PRINT_STRN(str, len) (void)0
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ endif
|
||||
# Make 'release' the default build type
|
||||
BTYPE ?= release
|
||||
|
||||
# Port for flashing firmware
|
||||
PORT ?= /dev/ttyUSB1
|
||||
|
||||
# If the build directory is not given, make it reflect the board name.
|
||||
BUILD ?= build/$(BOARD)/$(BTYPE)
|
||||
|
||||
@@ -23,6 +26,9 @@ CFLAGS += -Iboards/$(BOARD)
|
||||
|
||||
LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map
|
||||
|
||||
FLASH_SIZE_WIPY = 2M
|
||||
FLASH_SIZE_LAUNCHXL = 1M
|
||||
|
||||
ifeq ($(BTARGET), application)
|
||||
# qstr definitions (must come before including py.mk)
|
||||
QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
|
||||
@@ -39,3 +45,18 @@ endif
|
||||
|
||||
# always include MicroPython make rules
|
||||
include ../py/mkrules.mk
|
||||
|
||||
erase:
|
||||
cc3200tool -p $(PORT) format_flash --size $(FLASH_SIZE_$(BOARD))
|
||||
|
||||
deploy:
|
||||
cc3200tool -p $(PORT) \
|
||||
write_file bootmgr/build/$(BOARD)/$(BTYPE)/bootloader.bin /sys/mcuimg.bin \
|
||||
write_file build/$(BOARD)/$(BTYPE)/mcuimg.bin /sys/factimg.bin
|
||||
|
||||
# Files *.ucf and *ucf.signed.bin come from CC3200SDK-SERVICEPACK
|
||||
# package from http://www.ti.com/tool/cc3200sdk
|
||||
servicepack:
|
||||
cc3200tool -p $(PORT) \
|
||||
write_file --file-size=0x20000 --signature ota_1.0.1.6-2.7.0.0.ucf.signed.bin \
|
||||
ota_1.0.1.6-2.7.0.0.ucf /sys/servicepack.ucf
|
||||
|
||||
135
cc3200/README.md
135
cc3200/README.md
@@ -1,36 +1,66 @@
|
||||
# Build Instructions for the CC3200
|
||||
MicroPython port to CC3200 WiFi SoC
|
||||
===================================
|
||||
|
||||
Currently the CC3200 port of MicroPython builds under Linux and OSX **but not under Windows**.
|
||||
This is a MicroPython port to Texas Instruments CC3200 WiFi SoC (ARM Cortex-M4
|
||||
architecture). This port supports 2 boards: WiPy and TI CC3200-LAUNCHXL.
|
||||
|
||||
The tool chain required for the build can be found at <https://launchpad.net/gcc-arm-embedded>.
|
||||
## Build Instructions for the CC3200
|
||||
|
||||
In order to download the image to the CC3200 you will need the CCS_Uniflash tool from TI, which at this
|
||||
moment is only available for Windows, so, you need Linux/OSX to build and Windows to flash the image.
|
||||
Currently the CC3200 port of MicroPython builds under Linux and OSX,
|
||||
but not under Windows.
|
||||
|
||||
## To build an image suitable for debugging:
|
||||
The toolchain required for the build can be found at
|
||||
<https://launchpad.net/gcc-arm-embedded>.
|
||||
|
||||
In order to flash the image to the CC3200 you will need the
|
||||
[cc3200tool](https://github.com/ALLTERCO/cc3200tool). An alternative is
|
||||
to use CCS_Uniflash tool from TI, which works only under Windows, and all
|
||||
support is provided by TI itself.
|
||||
|
||||
Building the bootloader:
|
||||
|
||||
In order to debug the port specific code, optimizations need to be disabled on the
|
||||
port file (check the Makefile for specific details). You can use CCS from TI.
|
||||
Use the CC3200.ccxml file supplied with this distribution for the debuuger configuration.
|
||||
```bash
|
||||
make BTARGET=application BTYPE=debug BOARD=LAUNCHXL
|
||||
```
|
||||
## To build an image suitable to be flashed to the device:
|
||||
```bash
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL
|
||||
```
|
||||
## Building the bootloader
|
||||
```bash
|
||||
make BTARGET=bootloader BTYPE=release BOARD=LAUNCHXL
|
||||
```
|
||||
|
||||
## Regarding old revisions of the CC3200-LAUNCHXL
|
||||
First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and MicroPython cannot run
|
||||
there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this port, otherwise it won't work.
|
||||
Building the "release" image:
|
||||
|
||||
```
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL
|
||||
```
|
||||
|
||||
To build an image suitable for debugging:
|
||||
|
||||
In order to debug the port specific code, optimizations need to be disabled on the
|
||||
port file (check the Makefile for specific details). You can use CCS from TI.
|
||||
Use the CC3200.ccxml file supplied with this distribution for the debuuger configuration.
|
||||
|
||||
```
|
||||
make BTARGET=application BTYPE=debug BOARD=LAUNCHXL
|
||||
```
|
||||
|
||||
## Flashing the CC3200-LAUNCHXL
|
||||
|
||||
Note that WiPy comes factory programmed with a default version of MicroPython,
|
||||
it cannot be programmed via serial, and can be upgraded only with OTA (see
|
||||
below).
|
||||
|
||||
## Flashing the CC3200
|
||||
- Make sure that you have built both the *bootloader* and the *application* in **release** mode.
|
||||
- Make sure the SOP2 jumper is in position.
|
||||
- Make sure you Linux system recognized the board and created `ttyUSB*`
|
||||
devices (see below for configuration of `ftdi_sio` driver).
|
||||
- Run "make erase" and immediately press Reset button on the device.
|
||||
- Wait few seconds.
|
||||
- Run "make deploy" and immediately press Reset button on the device.
|
||||
- You are recommended to install the latest vendor WiFi firmware
|
||||
servicepack from http://www.ti.com/tool/cc3200sdk. Download
|
||||
CC3200SDK-SERVICEPACK package, install it, and locate `ota_*.ucf`
|
||||
and `ota_*.ucf.signed.bin` files. Copy them to the port's directory
|
||||
and run "make servicepack", with immediate press of Reset button.
|
||||
- Remove the SOP2 jumper and reset the board.
|
||||
|
||||
Flashing process using TI Uniflash:
|
||||
|
||||
- Open CCS_Uniflash and connect to the board (by default on port 22).
|
||||
- Format the serial flash (select 1MB size in case of the CC3200-LAUNCHXL, 2MB in case of the WiPy, leave the rest unchecked).
|
||||
- Mark the following files for erasing: `/cert/ca.pem`, `/cert/client.pem`, `/cert/private.key` and `/tmp/pac.bin`.
|
||||
@@ -40,26 +70,30 @@ there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this po
|
||||
- Flash the latest service pack (servicepack_1.0.0.10.0.bin) using the "Service Pack Update" button.
|
||||
- Close CCS_Uniflash, remove the SOP2 jumper and reset the board.
|
||||
|
||||
## Updating the board to with new software version
|
||||
- Make sure the board is running and connected to the same network as the computer.
|
||||
|
||||
```bash
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL WIPY_IP=192.168.1.1 WIPY_USER=micro WIPY_PWD=python deploy
|
||||
```
|
||||
|
||||
If `WIPY_IP`, `WIPY_USER` or `WIPY_PWD` are omitted the default values (the ones shown above) will be used.
|
||||
|
||||
## Playing with MicroPython and the CC3200:
|
||||
|
||||
Once the software is running, you have two options to access the MicroPython REPL:
|
||||
|
||||
- Through telnet.
|
||||
- Through telnet.
|
||||
* Connect to the network created by the board (as boots up in AP mode), **ssid = "wipy-wlan", key = "www.wipy.io"**.
|
||||
* You can also reinitialize the WLAN in station mode and connect to another AP, or in AP mode but with a
|
||||
different ssid and/or key.
|
||||
* Use your favourite telnet client with the following settings: **host = 192.168.1.1, port = 23.**
|
||||
* Log in with **user = "micro" and password = "python"**
|
||||
|
||||
- Through UART (serial).
|
||||
* This is enabled by default in the standard configuration, for UART0 (speed 115200).
|
||||
* For CC3200-LAUNCHXL, you will need to configure Linux `ftdi_sio` driver as described
|
||||
in the [blog post](http://www.achanceofbrainshowers.com/blog/tech/2014/8/19/cc3200-development-under-linux/).
|
||||
After that, connecting a board will create two `/dev/ttyUSB*` devices, a serial
|
||||
console is available on the 2nd one (usually `/dev/ttyUSB1`).
|
||||
* WiPy doesn't have onboard USB-UART converter, so you will need an external one,
|
||||
connected to GPIO01 (Tx) and GPIO02 (Rx).
|
||||
* Usage of UART port for REPL is controlled by MICROPY_STDIO_UART setting (and
|
||||
is done at the high level, using a suitable call to `os.dupterm()` function
|
||||
in boot.py, so you can override it at runtime regardless of MICROPY_STDIO_UART
|
||||
setting).
|
||||
|
||||
The board has a small file system of 192K (WiPy) or 64K (Launchpad) located in the serial flash connected to the CC3200.
|
||||
SD cards are also supported, you can connect any SD card and configure the pinout using the SD class API.
|
||||
|
||||
@@ -68,15 +102,19 @@ SD cards are also supported, you can connect any SD card and configure the pinou
|
||||
To upload your MicroPython scripts to the FTP server, open your FTP client of choice and connect to:
|
||||
**ftp://192.168.1.1, user = "micro", password = "python"**
|
||||
|
||||
I have tested the FTP server with **FileZilla, FireFTP, FireFox, IE and Chrome,** other clients should work as well, but I am
|
||||
not 100% sure of it.
|
||||
Tested FTP clients are: FileZilla, FireFTP, FireFox, IE and Chrome. Other
|
||||
clients should work as well, but you may need to configure them to use a
|
||||
single connection (this should be the default for any compliant FTP client).
|
||||
|
||||
## Upgrading the firmware Over The Air:
|
||||
## Upgrading the firmware Over The Air (OTA)
|
||||
|
||||
OTA software updates can be performed through the FTP server. After building a new **mcuimg.bin** in release mode, upload it to:
|
||||
`/flash/sys/mcuimg.bin` it will take around 6s (The TI simplelink file system is quite slow because every file is mirrored for
|
||||
safety). You won't see the file being stored inside `/flash/sys/` because it's actually saved bypassing FatFS, but rest assured that
|
||||
the file was successfully transferred, and it has been signed with a MD5 checksum to verify its integrity.
|
||||
OTA software updates can be performed through the builtin FTP server. After
|
||||
building a new `mcuimg.bin` in release mode, upload it to:
|
||||
`/flash/sys/mcuimg.bin`. It will take around 6s (The TI SimpleLink file
|
||||
system is quite slow because every file is mirrored for safety). You won't
|
||||
see the file being stored inside `/flash/sys/` because it's actually saved
|
||||
bypassing FatFS, but rest assured that the file was successfully transferred,
|
||||
and it has been signed with a MD5 checksum to verify its integrity.
|
||||
Now, reset the MCU by pressing the switch on the board, or by typing:
|
||||
|
||||
```python
|
||||
@@ -84,10 +122,27 @@ import machine
|
||||
machine.reset()
|
||||
```
|
||||
|
||||
### Note regarding FileZilla:
|
||||
There's a script which automates this process from the host side:
|
||||
|
||||
- Make sure the board is running and connected to the same network as the computer.
|
||||
|
||||
```bash
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL WIPY_IP=192.168.1.1 WIPY_USER=micro WIPY_PWD=python deploy-ota
|
||||
```
|
||||
|
||||
If `WIPY_IP`, `WIPY_USER` or `WIPY_PWD` are omitted the default values (the ones shown above) will be used.
|
||||
|
||||
|
||||
## Notes and known issues
|
||||
|
||||
## Regarding old revisions of the CC3200-LAUNCHXL
|
||||
|
||||
First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and MicroPython cannot run
|
||||
there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this port, otherwise it won't work.
|
||||
|
||||
### Note regarding FileZilla
|
||||
|
||||
Do not use the quick connect button, instead, open the site manager and create a new configuration. In the "General" tab make
|
||||
sure that encryption is set to: "Only use plain FTP (insecure)". In the Transfer Settings tab limit the max number of connections
|
||||
to one, otherwise FileZilla will try to open a second command connection when retrieving and saving files, and for simplicity and
|
||||
to reduce code size, only one command and one data connections are possible.
|
||||
|
||||
|
||||
@@ -154,7 +154,6 @@ APP_LIB_SRC_C = $(addprefix lib/,\
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
)
|
||||
|
||||
APP_STM_SRC_C = $(addprefix stmhal/,\
|
||||
@@ -163,8 +162,6 @@ APP_STM_SRC_C = $(addprefix stmhal/,\
|
||||
import.c \
|
||||
input.c \
|
||||
irq.c \
|
||||
lexerfatfs.c \
|
||||
moduselect.c \
|
||||
pybstdio.c \
|
||||
)
|
||||
|
||||
@@ -209,9 +206,9 @@ WIPY_PWD ?= 'python'
|
||||
|
||||
all: $(BUILD)/mcuimg.bin
|
||||
|
||||
.PHONY: deploy
|
||||
.PHONY: deploy-ota
|
||||
|
||||
deploy: $(BUILD)/mcuimg.bin
|
||||
deploy-ota: $(BUILD)/mcuimg.bin
|
||||
$(ECHO) "Writing $< to the board"
|
||||
$(Q)$(PYTHON) $(UPDATE_WIPY) --verify --ip $(WIPY_IP) --user $(WIPY_USER) --password $(WIPY_PWD) --file $<
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#define MICROPY_HW_ANTENNA_DIVERSITY (0)
|
||||
|
||||
#define MICROPY_STDIO_UART 0
|
||||
#define MICROPY_STDIO_UART 1
|
||||
#define MICROPY_STDIO_UART_BAUD 115200
|
||||
|
||||
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA1
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
|
||||
#define MICROPY_HW_ANTENNA_DIVERSITY (1)
|
||||
|
||||
#define MICROPY_STDIO_UART 1
|
||||
#define MICROPY_STDIO_UART_BAUD 115200
|
||||
|
||||
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA3
|
||||
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3
|
||||
#define MICROPY_SYS_LED_PORT GPIOA3_BASE
|
||||
|
||||
@@ -130,10 +130,6 @@ void mp_hal_delay_ms(mp_uint_t delay) {
|
||||
}
|
||||
}
|
||||
|
||||
NORETURN void mp_hal_raise(int errno) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, mp_obj_new_int(errno)));
|
||||
}
|
||||
|
||||
void mp_hal_set_interrupt_char (int c) {
|
||||
mpexception_set_interrupt_char (c);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
extern void HAL_SystemInit (void);
|
||||
extern void HAL_SystemDeInit (void);
|
||||
extern void HAL_IncrementTick(void);
|
||||
extern NORETURN void mp_hal_raise(int errno);
|
||||
extern void mp_hal_set_interrupt_char (int c);
|
||||
|
||||
#endif /* CC3200_LAUNCHXL_HAL_CC3200_HAL_H_ */
|
||||
|
||||
@@ -112,7 +112,7 @@ void mp_irq_remove (const mp_obj_t parent) {
|
||||
|
||||
uint mp_irq_translate_priority (uint priority) {
|
||||
if (priority < 1 || priority > MP_ARRAY_SIZE(mp_irq_priorities)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
return mp_irq_priorities[priority - 1];
|
||||
}
|
||||
@@ -176,7 +176,7 @@ STATIC mp_obj_t mp_irq_flags (mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags);
|
||||
|
||||
STATIC mp_obj_t mp_irq_call (mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
mp_irq_handler (self_in);
|
||||
return mp_const_none;
|
||||
|
||||
@@ -130,7 +130,7 @@ STATIC mp_obj_t machine_main(mp_obj_t main) {
|
||||
if (MP_OBJ_IS_STR(main)) {
|
||||
MP_STATE_PORT(machine_config_main) = main;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -198,7 +198,8 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, // legacy constant
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) },
|
||||
@@ -212,6 +213,5 @@ STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table
|
||||
|
||||
const mp_obj_module_t machine_module = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_umachine,
|
||||
.globals = (mp_obj_dict_t*)&machine_module_globals,
|
||||
};
|
||||
|
||||
@@ -91,7 +91,7 @@ STATIC const mp_arg_t network_server_args[] = {
|
||||
{ MP_QSTR_login, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -101,7 +101,7 @@ STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, mp_uint_t n_a
|
||||
// check the server id
|
||||
if (args[0].u_obj != MP_OBJ_NULL) {
|
||||
if (mp_obj_get_int(args[0].u_obj) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals
|
||||
|
||||
const mp_obj_module_t mp_module_network = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_network,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_network_globals,
|
||||
};
|
||||
|
||||
|
||||
@@ -58,6 +58,5 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globa
|
||||
|
||||
const mp_obj_module_t mp_module_ubinascii = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_ubinascii,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_binascii_globals,
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@ STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) {
|
||||
self->digested = false;
|
||||
}
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ STATIC mp_obj_t hash_read (mp_obj_t self_in) {
|
||||
}
|
||||
} else if (self->c_size < self->b_size) {
|
||||
// it's a fixed len block which is still incomplete
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
|
||||
if (!self->digested) {
|
||||
@@ -121,7 +121,7 @@ STATIC mp_obj_t hash_read (mp_obj_t self_in) {
|
||||
|
||||
/// \classmethod \constructor([data[, block_size]])
|
||||
/// initial data must be given if block_size wants to be passed
|
||||
STATIC mp_obj_t hash_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hash_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 2, false);
|
||||
mp_obj_hash_t *self = m_new0(mp_obj_hash_t, 1);
|
||||
self->base.type = type_in;
|
||||
@@ -204,7 +204,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals
|
||||
|
||||
const mp_obj_module_t mp_module_uhashlib = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_uhashlib,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_hashlib_globals,
|
||||
};
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ STATIC void mount (mp_obj_t device, const char *path, uint pathlen, bool readonl
|
||||
#endif
|
||||
// cannot mount twice or on existing paths
|
||||
if (f_stat(path, &fno) == FR_OK || osmount_find_by_device(device)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
|
||||
// create a new object
|
||||
@@ -196,7 +196,7 @@ STATIC void mount (mp_obj_t device, const char *path, uint pathlen, bool readonl
|
||||
if (f_mount(&self->fatfs, self->path, 1) != FR_OK) {
|
||||
// remove it and raise
|
||||
mp_obj_list_remove(&MP_STATE_PORT(mount_obj_list), self);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
|
||||
// mount succeeded, increment the count
|
||||
@@ -252,7 +252,7 @@ STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
|
||||
}
|
||||
|
||||
if (res != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
@@ -263,7 +263,7 @@ STATIC mp_obj_t os_getcwd(void) {
|
||||
char buf[MICROPY_ALLOC_PATH_MAX + 1];
|
||||
FRESULT res = f_getcwd(buf, sizeof buf);
|
||||
if (res != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||
}
|
||||
return mp_obj_new_str(buf, strlen(buf), false);
|
||||
}
|
||||
@@ -303,7 +303,7 @@ STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
|
||||
res = f_opendir(&dir, path); /* Open the directory */
|
||||
if (res != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
|
||||
for ( ; ; ) {
|
||||
@@ -335,10 +335,10 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
|
||||
case FR_OK:
|
||||
return mp_const_none;
|
||||
case FR_EXIST:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
break;
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
|
||||
@@ -351,7 +351,7 @@ STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) {
|
||||
case FR_OK:
|
||||
return mp_const_none;
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
|
||||
@@ -363,7 +363,7 @@ STATIC mp_obj_t os_remove(mp_obj_t path_o) {
|
||||
case FR_OK:
|
||||
return mp_const_none;
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
|
||||
@@ -394,7 +394,7 @@ STATIC mp_obj_t os_stat(mp_obj_t path_in) {
|
||||
fno.ftime = 0;
|
||||
fno.fattrib = AM_DIR;
|
||||
} else if ((res = f_stat(path, &fno)) != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||
}
|
||||
|
||||
mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL);
|
||||
@@ -481,7 +481,7 @@ STATIC mp_obj_t os_mount(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
return mp_const_none;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_value_invalid_arguments);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(os_mount_obj, 2, os_mount);
|
||||
|
||||
@@ -490,7 +490,7 @@ STATIC mp_obj_t os_unmount(mp_obj_t path_o) {
|
||||
|
||||
// '/flash' cannot be unmounted, also not the current working directory
|
||||
if (path_equal(path, "/flash")) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
|
||||
// now unmount it
|
||||
@@ -498,7 +498,7 @@ STATIC mp_obj_t os_unmount(mp_obj_t path_o) {
|
||||
if ((mount_obj = osmount_find_by_path(path))) {
|
||||
unmount (mount_obj);
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_msg(&mp_type_ValueError, mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
@@ -515,7 +515,7 @@ STATIC mp_obj_t os_mkfs(mp_obj_t device) {
|
||||
path = mp_obj_str_get_str(device);
|
||||
// otherwise the relative path check will pass...
|
||||
if (path[0] != '/') {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_value_invalid_arguments);
|
||||
}
|
||||
} else {
|
||||
// mount it briefly
|
||||
@@ -541,7 +541,7 @@ STATIC mp_obj_t os_mkfs(mp_obj_t device) {
|
||||
}
|
||||
|
||||
if (res != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -602,6 +602,5 @@ STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uos = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_uos,
|
||||
.globals = (mp_obj_dict_t*)&os_module_globals,
|
||||
};
|
||||
|
||||
@@ -127,7 +127,7 @@ void modusocket_close_all_user_sockets (void) {
|
||||
// socket class
|
||||
|
||||
// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
|
||||
STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 4, false);
|
||||
|
||||
// create socket object
|
||||
@@ -156,7 +156,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_
|
||||
// create the socket
|
||||
int _errno;
|
||||
if (wlan_socket_socket(s, &_errno) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
// add the socket to the list
|
||||
modusocket_socket_add(s->sock_base.sd, true);
|
||||
@@ -182,7 +182,7 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
// call the NIC to bind the socket
|
||||
int _errno;
|
||||
if (wlan_socket_bind(self, ip, port, &_errno) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -200,7 +200,7 @@ STATIC mp_obj_t socket_listen(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
|
||||
int _errno;
|
||||
if (wlan_socket_listen(self, backlog, &_errno) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -220,7 +220,7 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
|
||||
mp_uint_t port;
|
||||
int _errno;
|
||||
if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
|
||||
// add the socket to the list
|
||||
@@ -248,7 +248,7 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) {
|
||||
return mp_const_none;
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -262,7 +262,7 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
|
||||
int _errno;
|
||||
mp_int_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno);
|
||||
if (ret < 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
return mp_obj_new_int_from_uint(ret);
|
||||
}
|
||||
@@ -278,9 +278,9 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno);
|
||||
if (ret < 0) {
|
||||
if (_errno == EAGAIN && self->sock_base.has_timeout) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out"));
|
||||
mp_raise_msg(&mp_type_TimeoutError, "timed out");
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
if (ret == 0) {
|
||||
return mp_const_empty_bytes;
|
||||
@@ -307,7 +307,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
|
||||
int _errno;
|
||||
mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
|
||||
if (ret < 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
return mp_obj_new_int(ret);
|
||||
}
|
||||
@@ -324,9 +324,9 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
|
||||
if (ret < 0) {
|
||||
if (_errno == EAGAIN && self->sock_base.has_timeout) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out"));
|
||||
mp_raise_msg(&mp_type_TimeoutError, "timed out");
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
mp_obj_t tuple[2];
|
||||
if (ret == 0) {
|
||||
@@ -364,7 +364,7 @@ STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
|
||||
int _errno;
|
||||
if (wlan_socket_setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -384,7 +384,7 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
|
||||
}
|
||||
int _errno;
|
||||
if (wlan_socket_settimeout(self, timeout, &_errno) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
|
||||
mp_raise_OSError(-_errno);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -408,7 +408,7 @@ STATIC mp_obj_t socket_makefile(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args > 1) {
|
||||
const char *mode = mp_obj_str_get_str(args[1]);
|
||||
if (strcmp(mode, "rb") && strcmp(mode, "wb")) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
@@ -434,7 +434,6 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
|
||||
|
||||
// stream methods
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
@@ -446,7 +445,7 @@ STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *e
|
||||
mod_network_socket_obj_t *self = self_in;
|
||||
mp_int_t ret = wlan_socket_recv(self, buf, size, errcode);
|
||||
if (ret < 0) {
|
||||
// we need to ignore the socket closed error here because a readall() or read() without params
|
||||
// we need to ignore the socket closed error here because a read() without params
|
||||
// only returns when the socket is closed by the other end
|
||||
if (*errcode != SL_ESECCLOSED) {
|
||||
ret = MP_STREAM_ERROR;
|
||||
@@ -504,7 +503,7 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
|
||||
uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
|
||||
int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET);
|
||||
if (result < 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-result)));
|
||||
mp_raise_OSError(-result);
|
||||
}
|
||||
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
|
||||
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
|
||||
@@ -541,6 +540,5 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals
|
||||
|
||||
const mp_obj_module_t mp_module_usocket = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_usocket,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_usocket_globals,
|
||||
};
|
||||
|
||||
@@ -78,6 +78,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
|
||||
{ MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} },
|
||||
{ MP_QSTR_ssl_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SL_SO_SEC_METHOD_TLSV1} },
|
||||
{ MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
@@ -93,17 +94,19 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
|
||||
// retrieve the file paths (with an 6 byte offset in order to strip it from the '/flash' prefix)
|
||||
const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]);
|
||||
const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]);
|
||||
const char *cafile = (args[5].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
|
||||
NULL : &(mp_obj_str_get_str(args[5].u_obj)[6]);
|
||||
const char *cafile = (args[6].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
|
||||
NULL : &(mp_obj_str_get_str(args[6].u_obj)[6]);
|
||||
|
||||
// server side requires both certfile and keyfile
|
||||
if (args[3].u_bool && (!keyfile || !certfile)) {
|
||||
goto arg_error;
|
||||
}
|
||||
|
||||
_i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
|
||||
_i16 _errno;
|
||||
_u8 method = SL_SO_SEC_METHOD_TLSV1;
|
||||
_i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
|
||||
|
||||
// set the requested SSL method
|
||||
_u8 method = args[5].u_int;
|
||||
if ((_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method))) < 0) {
|
||||
goto socket_error;
|
||||
}
|
||||
@@ -128,10 +131,10 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
|
||||
return ssl_sock;
|
||||
|
||||
socket_error:
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
|
||||
mp_raise_OSError(_errno);
|
||||
|
||||
arg_error:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 0, mod_ssl_wrap_socket);
|
||||
|
||||
@@ -146,13 +149,17 @@ STATIC const mp_map_elem_t mp_module_ussl_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_NONE), MP_OBJ_NEW_SMALL_INT(SSL_CERT_NONE) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_OPTIONAL), MP_OBJ_NEW_SMALL_INT(SSL_CERT_OPTIONAL) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_REQUIRED), MP_OBJ_NEW_SMALL_INT(SSL_CERT_REQUIRED) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_SSLv3), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_SSLV3) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_TLSv1), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_TLSV1) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_TLSv1_1), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_TLSV1_1) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_TLSv1_2), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_TLSV1_2) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ussl_globals, mp_module_ussl_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ussl = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_ussl,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_ussl_globals,
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/smallint.h"
|
||||
#include "py/mphal.h"
|
||||
@@ -109,7 +109,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
|
||||
|
||||
// localtime generates a tuple of len 8. CPython uses 9, so we accept both.
|
||||
if (len < 8 || len > 9) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
|
||||
mp_raise_TypeError(mpexception_num_type_invalid_arguments);
|
||||
}
|
||||
|
||||
return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),
|
||||
@@ -196,6 +196,5 @@ STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_utime = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_utime,
|
||||
.globals = (mp_obj_dict_t*)&time_module_globals,
|
||||
};
|
||||
|
||||
@@ -26,6 +26,5 @@ STATIC MP_DEFINE_CONST_DICT(wipy_module_globals, wipy_module_globals_table);
|
||||
|
||||
const mp_obj_module_t wipy_module = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_wipy,
|
||||
.globals = (mp_obj_dict_t*)&wipy_module_globals,
|
||||
};
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
#include "modnetwork.h"
|
||||
#include "modusocket.h"
|
||||
#include "modwlan.h"
|
||||
#include "pybioctl.h"
|
||||
#include "pybrtc.h"
|
||||
#include "debug.h"
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
@@ -603,7 +602,7 @@ STATIC void wlan_reset (void) {
|
||||
|
||||
STATIC void wlan_validate_mode (uint mode) {
|
||||
if (mode != ROLE_STA && mode != ROLE_AP) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,7 +613,7 @@ STATIC void wlan_set_mode (uint mode) {
|
||||
|
||||
STATIC void wlan_validate_ssid_len (uint32_t len) {
|
||||
if (len > MODWLAN_SSID_LEN_MAX) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,7 +646,7 @@ STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len)
|
||||
return;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) {
|
||||
@@ -670,7 +669,7 @@ STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) {
|
||||
|
||||
STATIC void wlan_validate_channel (uint8_t channel) {
|
||||
if (channel < 1 || channel > 11) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -682,7 +681,7 @@ STATIC void wlan_set_channel (uint8_t channel) {
|
||||
#if MICROPY_HW_ANTENNA_DIVERSITY
|
||||
STATIC void wlan_validate_antenna (uint8_t antenna) {
|
||||
if (antenna != ANTENNA_TYPE_INTERNAL && antenna != ANTENNA_TYPE_EXTERNAL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,7 +829,7 @@ STATIC const mp_arg_t wlan_init_args[] = {
|
||||
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} },
|
||||
};
|
||||
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -847,7 +846,7 @@ STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_ui
|
||||
if (n_args > 1 || n_kw > 0) {
|
||||
// check the peripheral id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
// start the peripheral
|
||||
wlan_init_helper(self, &args[1]);
|
||||
@@ -871,7 +870,7 @@ STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
|
||||
|
||||
// check for correct wlan mode
|
||||
if (wlan_obj.mode == ROLE_AP) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
|
||||
Sl_WlanNetworkEntry_t wlanEntry;
|
||||
@@ -925,7 +924,7 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
|
||||
// check for the correct wlan mode
|
||||
if (wlan_obj.mode == ROLE_AP) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
|
||||
// parse args
|
||||
@@ -973,9 +972,9 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
modwlan_Status_t status;
|
||||
status = wlan_do_connect (ssid, ssid_len, bssid, auth, key, key_len, timeout);
|
||||
if (status == MODWLAN_ERROR_TIMEOUT) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
} else if (status == MODWLAN_ERROR_INVALID_PARAMS) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -1004,7 +1003,7 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
|
||||
|
||||
// check the interface id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// get the configuration
|
||||
@@ -1051,7 +1050,7 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
|
||||
// check for the correct string
|
||||
const char *mode = mp_obj_str_get_str(args[1].u_obj);
|
||||
if (strcmp("dhcp", mode)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
// only if we are not in AP mode
|
||||
@@ -1165,7 +1164,7 @@ STATIC mp_obj_t wlan_mac (mp_uint_t n_args, const mp_obj_t *args) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len != 6) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
memcpy(self->mac, bufinfo.buf, SL_MAC_ADDR_LEN);
|
||||
sl_NetCfgSet(SL_MAC_ADDRESS_SET, 1, SL_MAC_ADDR_LEN, (_u8 *)self->mac);
|
||||
@@ -1201,7 +1200,7 @@ STATIC mp_obj_t wlan_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *
|
||||
return _irq;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq);
|
||||
|
||||
@@ -1230,18 +1229,18 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq);
|
||||
//
|
||||
// // the call to sl_NetAppSet corrupts the input string URN=args[1], so we copy into a local buffer
|
||||
// if (len > MAX_DEVICE_URN_LEN) {
|
||||
// nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
// mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
// }
|
||||
// strcpy(urn, p);
|
||||
//
|
||||
// if (sl_NetAppSet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, len, (unsigned char *)urn) < 0) {
|
||||
// nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// // get the URN
|
||||
// if (sl_NetAppGet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, &len, (uint8_t *)urn) < 0) {
|
||||
// nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
// }
|
||||
// return mp_obj_new_str(urn, (len - 1), false);
|
||||
// }
|
||||
@@ -1250,6 +1249,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq);
|
||||
//}
|
||||
//STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_urn_obj, 1, 2, wlan_urn);
|
||||
|
||||
STATIC mp_obj_t wlan_print_ver(void) {
|
||||
SlVersionFull ver;
|
||||
byte config_opt = SL_DEVICE_GENERAL_VERSION;
|
||||
byte config_len = sizeof(ver);
|
||||
sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver);
|
||||
printf("NWP: %d.%d.%d.%d\n", ver.NwpVersion[0], ver.NwpVersion[1], ver.NwpVersion[2], ver.NwpVersion[3]);
|
||||
printf("MAC: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.FwVersion[0], ver.ChipFwAndPhyVersion.FwVersion[1],
|
||||
ver.ChipFwAndPhyVersion.FwVersion[2], ver.ChipFwAndPhyVersion.FwVersion[3]);
|
||||
printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1],
|
||||
ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(wlan_print_ver_fun_obj, wlan_print_ver);
|
||||
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(wlan_print_ver_obj, MP_ROM_PTR(&wlan_print_ver_fun_obj));
|
||||
|
||||
STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&wlan_init_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&wlan_scan_obj },
|
||||
@@ -1266,6 +1280,7 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&wlan_irq_obj },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_connections), (mp_obj_t)&wlan_connections_obj },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_urn), (mp_obj_t)&wlan_urn_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_print_ver), (mp_obj_t)&wlan_print_ver_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_STA), MP_OBJ_NEW_SMALL_INT(ROLE_STA) },
|
||||
@@ -1461,7 +1476,7 @@ int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int
|
||||
|
||||
int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
|
||||
mp_int_t ret;
|
||||
if (request == MP_IOCTL_POLL) {
|
||||
if (request == MP_STREAM_POLL) {
|
||||
mp_uint_t flags = arg;
|
||||
ret = 0;
|
||||
int32_t sd = s->sock_base.sd;
|
||||
@@ -1473,13 +1488,13 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t
|
||||
FD_ZERO(&xfds);
|
||||
|
||||
// set fds if needed
|
||||
if (flags & MP_IOCTL_POLL_RD) {
|
||||
if (flags & MP_STREAM_POLL_RD) {
|
||||
FD_SET(sd, &rfds);
|
||||
}
|
||||
if (flags & MP_IOCTL_POLL_WR) {
|
||||
if (flags & MP_STREAM_POLL_WR) {
|
||||
FD_SET(sd, &wfds);
|
||||
}
|
||||
if (flags & MP_IOCTL_POLL_HUP) {
|
||||
if (flags & MP_STREAM_POLL_HUP) {
|
||||
FD_SET(sd, &xfds);
|
||||
}
|
||||
|
||||
@@ -1497,13 +1512,13 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t
|
||||
|
||||
// check return of select
|
||||
if (FD_ISSET(sd, &rfds)) {
|
||||
ret |= MP_IOCTL_POLL_RD;
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
if (FD_ISSET(sd, &wfds)) {
|
||||
ret |= MP_IOCTL_POLL_WR;
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
if (FD_ISSET(sd, &xfds)) {
|
||||
ret |= MP_IOCTL_POLL_HUP;
|
||||
ret |= MP_STREAM_POLL_HUP;
|
||||
}
|
||||
} else {
|
||||
*_errno = EINVAL;
|
||||
|
||||
@@ -104,7 +104,7 @@ STATIC void pyb_adc_init (pyb_adc_obj_t *self) {
|
||||
STATIC void pyb_adc_check_init(void) {
|
||||
// not initialized
|
||||
if (!pyb_adc_obj.enabled) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ STATIC const mp_arg_t pyb_adc_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 12} },
|
||||
};
|
||||
STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -149,12 +149,12 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uin
|
||||
|
||||
// check the peripheral id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// check the number of bits
|
||||
if (args[1].u_int != 12) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
// setup the object
|
||||
@@ -173,7 +173,7 @@ STATIC mp_obj_t adc_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_adc_init_args[1], args);
|
||||
// check the number of bits
|
||||
if (args[0].u_int != 12) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
pyb_adc_init(pos_args[0]);
|
||||
return mp_const_none;
|
||||
@@ -206,11 +206,11 @@ STATIC mp_obj_t adc_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t
|
||||
if (args[0].u_obj != MP_OBJ_NULL) {
|
||||
ch_id = mp_obj_get_int(args[0].u_obj);
|
||||
if (ch_id >= PYB_ADC_NUM_CHANNELS) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_ValueError(mpexception_os_resource_not_avaliable);
|
||||
} else if (args[1].u_obj != mp_const_none) {
|
||||
uint pin_ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0);
|
||||
if (ch_id != pin_ch_id) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -277,7 +277,7 @@ STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) {
|
||||
|
||||
// the channel must be enabled
|
||||
if (!self->enabled) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
|
||||
// wait until a new value is available
|
||||
@@ -289,7 +289,7 @@ STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_value_obj, adc_channel_value);
|
||||
|
||||
STATIC mp_obj_t adc_channel_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t adc_channel_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
return adc_channel_value (self_in);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ STATIC bool pyb_i2c_transaction(uint cmd) {
|
||||
STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
|
||||
// not initialized
|
||||
if (!self->baudrate) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ STATIC void pyb_i2c_read_into (mp_arg_val_t *args, vstr_t *vstr) {
|
||||
|
||||
// receive the data
|
||||
if (!pyb_i2c_read(args[0].u_int, (byte *)vstr->buf, vstr->len)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
|
||||
if (pyb_i2c_mem_addr_write (i2c_addr, (byte *)&mem_addr, mem_addr_size)) {
|
||||
// Read the specified length of data
|
||||
if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,7 +323,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, const mp_arg_val_t *arg
|
||||
return mp_const_none;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC const mp_arg_t pyb_i2c_init_args[] = {
|
||||
@@ -332,7 +332,7 @@ STATIC const mp_arg_t pyb_i2c_init_args[] = {
|
||||
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
|
||||
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -341,7 +341,7 @@ STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
|
||||
|
||||
// check the peripheral id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// setup the object
|
||||
@@ -445,7 +445,7 @@ STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_m
|
||||
|
||||
// send the data
|
||||
if (!pyb_i2c_write(args[0].u_int, bufinfo.buf, bufinfo.len, args[2].u_bool)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
|
||||
// return the number of bytes written
|
||||
@@ -514,7 +514,7 @@ STATIC mp_obj_t pyb_i2c_writeto_mem(mp_uint_t n_args, const mp_obj_t *pos_args,
|
||||
return mp_obj_new_int(bufinfo.len);
|
||||
}
|
||||
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem);
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ pin_obj_t *pin_find(mp_obj_t user_obj) {
|
||||
return pin_obj;
|
||||
}
|
||||
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
void pin_config (pin_obj_t *self, int af, uint mode, uint pull, int value, uint strength) {
|
||||
@@ -185,7 +185,7 @@ uint8_t pin_find_peripheral_unit (const mp_obj_t pin, uint8_t fn, uint8_t type)
|
||||
return pin_o->af_list[i].unit;
|
||||
}
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit) {
|
||||
@@ -195,13 +195,13 @@ uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit)
|
||||
return pin_o->af_list[i].type;
|
||||
}
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) {
|
||||
int8_t af = pin_obj_find_af(pin, fn, unit, type);
|
||||
if (af < 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
return af;
|
||||
}
|
||||
@@ -426,18 +426,18 @@ STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t prio
|
||||
STATIC void pin_validate_mode (uint mode) {
|
||||
if (mode != GPIO_DIR_MODE_IN && mode != GPIO_DIR_MODE_OUT && mode != PIN_TYPE_OD &&
|
||||
mode != GPIO_DIR_MODE_ALT && mode != GPIO_DIR_MODE_ALT_OD) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
STATIC void pin_validate_pull (uint pull) {
|
||||
if (pull != PIN_TYPE_STD && pull != PIN_TYPE_STD_PU && pull != PIN_TYPE_STD_PD) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void pin_validate_drive(uint strength) {
|
||||
if (strength != PIN_STRENGTH_2MA && strength != PIN_STRENGTH_4MA && strength != PIN_STRENGTH_6MA) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ STATIC void pin_validate_af(const pin_obj_t* pin, int8_t idx, uint8_t *fn, uint8
|
||||
return;
|
||||
}
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC uint8_t pin_get_value (const pin_obj_t* self) {
|
||||
@@ -591,7 +591,7 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_
|
||||
return mp_const_none;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
@@ -647,7 +647,7 @@ STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
|
||||
mp_printf(print, ", alt=%d)", alt);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// Run an argument through the mapper and return the result.
|
||||
@@ -747,7 +747,7 @@ STATIC mp_obj_t pin_drive(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_drive_obj, 1, 2, pin_drive);
|
||||
|
||||
STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_t _args[2] = {self_in, *args};
|
||||
return pin_value (n_args + 1, _args);
|
||||
@@ -905,7 +905,7 @@ STATIC mp_obj_t pin_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
return _irq;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_irq_obj, 1, pin_irq);
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) {
|
||||
|
||||
// verify the tuple
|
||||
if (len < 3 || len > 8) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
tm.tm_year = mp_obj_get_int(items[0]);
|
||||
@@ -285,7 +285,7 @@ STATIC const mp_arg_t pyb_rtc_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_datetime, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -294,7 +294,7 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
|
||||
|
||||
// check the peripheral id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// setup the object
|
||||
@@ -362,7 +362,7 @@ STATIC mp_obj_t pyb_rtc_alarm (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
|
||||
|
||||
// check the alarm id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
uint32_t f_seconds;
|
||||
@@ -371,7 +371,7 @@ STATIC mp_obj_t pyb_rtc_alarm (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
|
||||
if (MP_OBJ_IS_TYPE(args[1].u_obj, &mp_type_tuple)) { // datetime tuple given
|
||||
// repeat cannot be used with a datetime tuple
|
||||
if (repeat) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
f_mseconds = pyb_rtc_datetime_s_us (args[1].u_obj, &f_seconds) / 1000;
|
||||
} else { // then it must be an integer
|
||||
@@ -397,7 +397,7 @@ STATIC mp_obj_t pyb_rtc_alarm_left (mp_uint_t n_args, const mp_obj_t *args) {
|
||||
|
||||
// only alarm id 0 is available
|
||||
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// get the current time
|
||||
@@ -415,7 +415,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc
|
||||
STATIC mp_obj_t pyb_rtc_alarm_cancel (mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// only alarm id 0 is available
|
||||
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
// disable the alarm
|
||||
pyb_rtc_disable_alarm();
|
||||
@@ -453,7 +453,7 @@ STATIC mp_obj_t pyb_rtc_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
return _irq;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq);
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ STATIC const mp_obj_t pyb_sd_def_pin[3] = {&pin_GP10, &pin_GP11, &pin_GP15};
|
||||
DECLARE PRIVATE FUNCTIONS
|
||||
******************************************************************************/
|
||||
STATIC void pyb_sd_hw_init (pybsd_obj_t *self);
|
||||
STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
|
||||
STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
STATIC mp_obj_t pyb_sd_deinit (mp_obj_t self_in);
|
||||
|
||||
/******************************************************************************
|
||||
@@ -107,7 +107,7 @@ STATIC mp_obj_t pyb_sd_init_helper (pybsd_obj_t *self, const mp_arg_val_t *args)
|
||||
|
||||
pyb_sd_hw_init (self);
|
||||
if (sd_disk_init() != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
|
||||
// register it with the sleep module
|
||||
@@ -123,7 +123,7 @@ STATIC const mp_arg_t pyb_sd_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -132,7 +132,7 @@ STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp
|
||||
|
||||
// check the peripheral id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// setup and initialize the object
|
||||
|
||||
@@ -131,7 +131,7 @@ STATIC void pybspi_rx (pyb_spi_obj_t *self, void *data) {
|
||||
|
||||
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) {
|
||||
if (!self->baudrate) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
// send and receive the data
|
||||
MAP_SPICSEnable(GSPI_BASE);
|
||||
@@ -148,7 +148,7 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda
|
||||
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_spi_obj_t *self = self_in;
|
||||
if (self->baudrate > 0) {
|
||||
mp_printf(print, "SPI(0, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)",
|
||||
mp_printf(print, "SPI(0, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)",
|
||||
self->baudrate, (self->wlen * 8), self->polarity, self->phase);
|
||||
} else {
|
||||
mp_print_str(print, "SPI(0)");
|
||||
@@ -156,13 +156,8 @@ STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *args) {
|
||||
// verify that mode is master
|
||||
if (args[0].u_int != SPI_MODE_MASTER) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
uint bits;
|
||||
switch (args[2].u_int) {
|
||||
switch (args[1].u_int) {
|
||||
case 8:
|
||||
bits = SPI_WL_8;
|
||||
break;
|
||||
@@ -177,27 +172,27 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *arg
|
||||
break;
|
||||
}
|
||||
|
||||
uint polarity = args[3].u_int;
|
||||
uint phase = args[4].u_int;
|
||||
uint polarity = args[2].u_int;
|
||||
uint phase = args[3].u_int;
|
||||
if (polarity > 1 || phase > 1) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
uint firstbit = args[5].u_int;
|
||||
uint firstbit = args[4].u_int;
|
||||
if (firstbit != PYBSPI_FIRST_BIT_MSB) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
// build the configuration
|
||||
self->baudrate = args[1].u_int;
|
||||
self->wlen = args[2].u_int >> 3;
|
||||
self->baudrate = args[0].u_int;
|
||||
self->wlen = args[1].u_int >> 3;
|
||||
self->config = bits | SPI_CS_ACTIVELOW | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
|
||||
self->polarity = polarity;
|
||||
self->phase = phase;
|
||||
self->submode = (polarity << 1) | phase;
|
||||
|
||||
// assign the pins
|
||||
mp_obj_t pins_o = args[6].u_obj;
|
||||
mp_obj_t pins_o = args[5].u_obj;
|
||||
if (pins_o != mp_const_none) {
|
||||
mp_obj_t *pins;
|
||||
if (pins_o == MP_OBJ_NULL) {
|
||||
@@ -218,12 +213,11 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *arg
|
||||
return mp_const_none;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
static const mp_arg_t pyb_spi_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = SPI_MODE_MASTER} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1MHz
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
@@ -231,7 +225,7 @@ static const mp_arg_t pyb_spi_init_args[] = {
|
||||
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_FIRST_BIT_MSB} },
|
||||
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -240,7 +234,7 @@ STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
|
||||
|
||||
// check the peripheral id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// setup the object
|
||||
@@ -295,7 +289,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write);
|
||||
STATIC mp_obj_t pyb_spi_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
|
||||
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
|
||||
{ MP_QSTR_write, MP_ARG_INT, {.u_int = 0x00} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
@@ -319,7 +313,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read);
|
||||
STATIC mp_obj_t pyb_spi_readinto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
|
||||
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
|
||||
{ MP_QSTR_write, MP_ARG_INT, {.u_int = 0x00} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
@@ -357,7 +351,7 @@ STATIC mp_obj_t pyb_spi_write_readinto (mp_obj_t self, mp_obj_t writebuf, mp_obj
|
||||
// get the read buffer
|
||||
mp_get_buffer_raise(readbuf, &bufinfo_read, MP_BUFFER_WRITE);
|
||||
if (bufinfo_read.len != bufinfo_write.len) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,7 +373,6 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&pyb_spi_write_readinto_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MSB), MP_OBJ_NEW_SMALL_INT(PYBSPI_FIRST_BIT_MSB) },
|
||||
};
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t
|
||||
return prescaler;
|
||||
|
||||
error:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC void timer_init (pyb_timer_obj_t *tim) {
|
||||
@@ -319,17 +319,17 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
|
||||
return mp_const_none;
|
||||
|
||||
error:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// create a new Timer object
|
||||
int32_t timer_idx = mp_obj_get_int(args[0]);
|
||||
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx];
|
||||
@@ -370,7 +370,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
|
||||
// verify that the timer has been already initialized
|
||||
if (!tim->config) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) {
|
||||
// invalid channel
|
||||
@@ -440,7 +440,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
return ch;
|
||||
|
||||
error:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel);
|
||||
|
||||
@@ -560,7 +560,7 @@ STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// set
|
||||
int32_t _frequency = mp_obj_get_int(args[1]);
|
||||
if (_frequency <= 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
ch->frequency = _frequency;
|
||||
ch->period = 1000000 / _frequency;
|
||||
@@ -579,7 +579,7 @@ STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args)
|
||||
// set
|
||||
int32_t _period = mp_obj_get_int(args[1]);
|
||||
if (_period <= 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
ch->period = _period;
|
||||
ch->frequency = 1000000 / _period;
|
||||
@@ -712,7 +712,7 @@ STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_arg
|
||||
return _irq;
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_irq_obj, 1, pyb_timer_channel_irq);
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
#include "uart.h"
|
||||
#include "pybuart.h"
|
||||
#include "mpirq.h"
|
||||
#include "pybioctl.h"
|
||||
#include "pybsleep.h"
|
||||
#include "mpexception.h"
|
||||
#include "py/mpstate.h"
|
||||
@@ -280,7 +279,7 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) {
|
||||
STATIC void uart_check_init(pyb_uart_obj_t *self) {
|
||||
// not initialized
|
||||
if (!self->baudrate) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,7 +431,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a
|
||||
return mp_const_none;
|
||||
|
||||
error:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC const mp_arg_t pyb_uart_init_args[] = {
|
||||
@@ -443,7 +442,7 @@ STATIC const mp_arg_t pyb_uart_init_args[] = {
|
||||
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -472,7 +471,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, mp_uint_t n_args, m
|
||||
}
|
||||
|
||||
if (uart_id > PYB_UART_1) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
|
||||
// get the correct uart instance
|
||||
@@ -556,7 +555,7 @@ STATIC mp_obj_t pyb_uart_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
|
||||
return uart_irq_new (self, trigger, priority, args[2].u_obj);
|
||||
|
||||
invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq);
|
||||
|
||||
@@ -570,8 +569,6 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
|
||||
/// \method read([nbytes])
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
/// \method readall()
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
|
||||
/// \method readline()
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
|
||||
/// \method readinto(buf[, nbytes])
|
||||
@@ -622,7 +619,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
|
||||
|
||||
// write the data
|
||||
if (!uart_tx_strn(self, buf, size)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@@ -632,14 +629,14 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
|
||||
mp_uint_t ret;
|
||||
uart_check_init(self);
|
||||
|
||||
if (request == MP_IOCTL_POLL) {
|
||||
if (request == MP_STREAM_POLL) {
|
||||
mp_uint_t flags = arg;
|
||||
ret = 0;
|
||||
if ((flags & MP_IOCTL_POLL_RD) && uart_rx_any(self)) {
|
||||
ret |= MP_IOCTL_POLL_RD;
|
||||
if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self)) {
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
if ((flags & MP_IOCTL_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) {
|
||||
ret |= MP_IOCTL_POLL_WR;
|
||||
if ((flags & MP_STREAM_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) {
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
} else {
|
||||
*errcode = EINVAL;
|
||||
|
||||
@@ -92,7 +92,7 @@ STATIC const mp_arg_t pyb_wdt_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} }, // 5 s
|
||||
};
|
||||
STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// check the arguments
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@@ -100,14 +100,14 @@ STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
|
||||
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_wdt_init_args, args);
|
||||
|
||||
if (args[0].u_obj != mp_const_none && mp_obj_get_int(args[0].u_obj) > 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
||||
}
|
||||
uint timeout_ms = args[1].u_int;
|
||||
if (timeout_ms < PYBWDT_MIN_TIMEOUT_MS) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
if (pyb_wdt_obj.running) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
||||
}
|
||||
|
||||
// Enable the WDT peripheral clock
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
// options to control how Micro Python is built
|
||||
|
||||
#define MICROPY_ALLOC_PATH_MAX (128)
|
||||
#define MICROPY_PERSISTENT_CODE_LOAD (1)
|
||||
#define MICROPY_EMIT_THUMB (0)
|
||||
#define MICROPY_EMIT_INLINE_THUMB (0)
|
||||
#define MICROPY_COMP_MODULE_CONST (1)
|
||||
@@ -54,6 +55,7 @@
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
#define MICROPY_OPT_COMPUTED_GOTO (0)
|
||||
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
|
||||
#define MICROPY_READER_FATFS (1)
|
||||
#ifndef DEBUG // we need ram on the launchxl while debugging
|
||||
#define MICROPY_CPYTHON_COMPAT (1)
|
||||
#else
|
||||
@@ -111,6 +113,7 @@
|
||||
#define MICROPY_PY_URE (1)
|
||||
#define MICROPY_PY_UHEAPQ (0)
|
||||
#define MICROPY_PY_UHASHLIB (0)
|
||||
#define MICROPY_PY_USELECT (1)
|
||||
|
||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
||||
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
|
||||
@@ -185,14 +188,13 @@ extern const struct _mp_obj_module_t mp_module_ussl;
|
||||
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef unsigned int mp_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
||||
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
|
||||
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
|
||||
#define MICROPY_EVENT_POLL_HOOK __WFI();
|
||||
|
||||
// assembly functions to handle critical sections, interrupt
|
||||
// disabling/enabling and sleep mode enter/exit
|
||||
|
||||
@@ -98,7 +98,12 @@ static FATFS *sflash_fatfs;
|
||||
|
||||
static const char fresh_main_py[] = "# main.py -- put your code here!\r\n";
|
||||
static const char fresh_boot_py[] = "# boot.py -- run on boot-up\r\n"
|
||||
"# can run arbitrary Python, but best to keep it minimal\r\n";
|
||||
"# can run arbitrary Python, but best to keep it minimal\r\n"
|
||||
#if MICROPY_STDIO_UART
|
||||
"import os, machine\r\n"
|
||||
"os.dupterm(machine.UART(0, " MP_STRINGIFY(MICROPY_STDIO_UART_BAUD) "))\r\n"
|
||||
#endif
|
||||
;
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PUBLIC FUNCTIONS
|
||||
|
||||
@@ -28,10 +28,13 @@
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/mpstate.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mpthread.h"
|
||||
#include "py/mphal.h"
|
||||
#include "mptask.h"
|
||||
#include "task.h"
|
||||
#include "irq.h"
|
||||
|
||||
#if MICROPY_PY_THREAD
|
||||
|
||||
@@ -131,7 +134,7 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
|
||||
TaskHandle_t id = xTaskCreateStatic(freertos_entry, "Thread", *stack_size / sizeof(void*), arg, 2, stack, tcb);
|
||||
if (id == NULL) {
|
||||
mp_thread_mutex_unlock(&thread_mutex);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread"));
|
||||
mp_raise_msg(&mp_type_OSError, "can't create thread");
|
||||
}
|
||||
|
||||
// add thread to linked list of all threads
|
||||
@@ -165,14 +168,23 @@ void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
|
||||
mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer);
|
||||
}
|
||||
|
||||
// To allow hard interrupts to work with threading we only take/give the semaphore
|
||||
// if we are not within an interrupt context and interrupts are enabled.
|
||||
|
||||
int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
|
||||
int ret = xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0);
|
||||
return ret == pdTRUE;
|
||||
if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) {
|
||||
int ret = xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0);
|
||||
return ret == pdTRUE;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
|
||||
xSemaphoreGive(mutex->handle);
|
||||
// TODO check return value
|
||||
if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) {
|
||||
xSemaphoreGive(mutex->handle);
|
||||
// TODO check return value
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_THREAD
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/misc.h"
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "serverstask.h"
|
||||
#include "simplelink.h"
|
||||
@@ -187,7 +187,7 @@ void servers_close_socket (int16_t *sd) {
|
||||
|
||||
void servers_set_login (char *user, char *pass) {
|
||||
if (strlen(user) > SERVERS_USER_PASS_LEN_MAX || strlen(pass) > SERVERS_USER_PASS_LEN_MAX) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
memcpy(servers_user, user, SERVERS_USER_PASS_LEN_MAX);
|
||||
memcpy(servers_pass, pass, SERVERS_USER_PASS_LEN_MAX);
|
||||
@@ -196,7 +196,7 @@ void servers_set_login (char *user, char *pass) {
|
||||
void servers_set_timeout (uint32_t timeout) {
|
||||
if (timeout < SERVERS_MIN_TIMEOUT_MS) {
|
||||
// timeout is too low
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
servers_data.timeout = timeout;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ n_w = f.write(test_bytes)
|
||||
print(n_w == len(test_bytes))
|
||||
f.close()
|
||||
f = open('test.txt', 'r')
|
||||
r = bytes(f.readall(), 'ascii')
|
||||
r = bytes(f.read(), 'ascii')
|
||||
# check that we can write and read it correctly
|
||||
print(r == test_bytes)
|
||||
f.close()
|
||||
|
||||
@@ -30,6 +30,6 @@
|
||||
void rng_init0 (void);
|
||||
uint32_t rng_get (void);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(machine_rng_get_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_rng_get_obj);
|
||||
|
||||
#endif // __RANDOM_H
|
||||
|
||||
@@ -99,7 +99,7 @@ copyright = '2014-2016, Damien P. George and contributors'
|
||||
# The short X.Y version.
|
||||
version = '1.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.8.3'
|
||||
release = '1.8.7'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -58,6 +58,17 @@ For your convenience, some of technical specifications are provided below:
|
||||
and always-available BootROM bootloader, ESP8266 is not brickable.
|
||||
|
||||
|
||||
Scarcity of runtime resources
|
||||
-----------------------------
|
||||
|
||||
ESP8266 has very modest resources (first of all, RAM memory). So, please
|
||||
avoid allocating too big container objects (lists, dictionaries) and
|
||||
buffers. There is also no full-fledged OS to keep track of resources
|
||||
and automatically clean them up, so that's the task of a user/user
|
||||
application: please be sure to close open files, sockets, etc. as soon
|
||||
as possible after use.
|
||||
|
||||
|
||||
Boot process
|
||||
------------
|
||||
|
||||
@@ -71,13 +82,16 @@ and developers, who can diagnose themselves any issues arising from
|
||||
modifying the standard process).
|
||||
|
||||
Once the filesystem is mounted, ``boot.py`` is executed from it. The standard
|
||||
version of this file is created during first-time module set up and by
|
||||
default starts up a WebREPL daemon to handle incoming connections. This
|
||||
file is customizable by end users (for example, you may want to disable
|
||||
WebREPL for extra security, or add other services which should be run on
|
||||
version of this file is created during first-time module set up and has
|
||||
commands to start a WebREPL daemon (disabled by default, configurable
|
||||
with ``webrepl_setup`` module), etc. This
|
||||
file is customizable by end users (for example, you may want to set some
|
||||
parameters or add other services which should be run on
|
||||
a module start-up). But keep in mind that incorrect modifications to boot.py
|
||||
may still lead to boot loops or lock ups, requiring to reflash a module
|
||||
from scratch.
|
||||
from scratch. (In particular, it's recommended that you use either
|
||||
``webrepl_setup`` module or manual editing to configure WebREPL, but not
|
||||
both).
|
||||
|
||||
As a final step of boot procedure, ``main.py`` is executed from filesystem,
|
||||
if exists. This file is a hook to start up a user application each time
|
||||
|
||||
@@ -23,14 +23,14 @@ Tab-completion is useful to find out what methods an object has.
|
||||
Paste mode (ctrl-E) is useful to paste a large slab of Python code into
|
||||
the REPL.
|
||||
|
||||
The ``machine`` module::
|
||||
The :mod:`machine` module::
|
||||
|
||||
import machine
|
||||
|
||||
machine.freq() # get the current frequency of the CPU
|
||||
machine.freq(160000000) # set the CPU frequency to 160 MHz
|
||||
|
||||
The ``esp`` module::
|
||||
The :mod:`esp` module::
|
||||
|
||||
import esp
|
||||
|
||||
@@ -40,7 +40,7 @@ The ``esp`` module::
|
||||
Networking
|
||||
----------
|
||||
|
||||
The ``network`` module::
|
||||
The :mod:`network` module::
|
||||
|
||||
import network
|
||||
|
||||
@@ -69,13 +69,13 @@ A useful function for connecting to your local WiFi network is::
|
||||
pass
|
||||
print('network config:', wlan.ifconfig())
|
||||
|
||||
Once the network is established the ``socket`` module can be used
|
||||
Once the network is established the :mod:`socket <usocket>` module can be used
|
||||
to create and use TCP/UDP sockets as usual.
|
||||
|
||||
Delay and timing
|
||||
----------------
|
||||
|
||||
Use the ``time`` module::
|
||||
Use the :mod:`time <utime>` module::
|
||||
|
||||
import time
|
||||
|
||||
@@ -83,7 +83,7 @@ Use the ``time`` module::
|
||||
time.sleep_ms(500) # sleep for 500 milliseconds
|
||||
time.sleep_us(10) # sleep for 10 microseconds
|
||||
start = time.ticks_ms() # get millisecond counter
|
||||
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
|
||||
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
|
||||
|
||||
Timers
|
||||
------
|
||||
@@ -162,17 +162,18 @@ Use the ``machine.ADC`` class::
|
||||
adc = ADC(0) # create ADC object on ADC pin
|
||||
adc.read() # read value, 0-1024
|
||||
|
||||
SPI bus
|
||||
-------
|
||||
Software SPI bus
|
||||
----------------
|
||||
|
||||
The SPI driver is implemented in software and works on all pins::
|
||||
There are two SPI drivers. One is implemented in software (bit-banging)
|
||||
and works on all pins::
|
||||
|
||||
from machine import Pin, SPI
|
||||
|
||||
# construct an SPI bus on the given pins
|
||||
# polarity is the idle state of SCK
|
||||
# phase=0 means sample on the first edge of SCK, phase=1 means the second
|
||||
spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
|
||||
spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
|
||||
|
||||
spi.init(baudrate=200000) # set the baudrate
|
||||
|
||||
@@ -189,6 +190,21 @@ The SPI driver is implemented in software and works on all pins::
|
||||
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
|
||||
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
|
||||
|
||||
|
||||
Hardware SPI bus
|
||||
----------------
|
||||
|
||||
The hardware SPI is faster (up to 80Mhz), but only works on following pins:
|
||||
``MISO`` is GPIO12, ``MOSI`` is GPIO13, and ``SCK`` is GPIO14. It has the same
|
||||
methods as the bitbanging SPI class above, except for the pin parameters for the
|
||||
constructor and init (as those are fixed)::
|
||||
|
||||
from machine import Pin, SPI
|
||||
|
||||
hspi = SPI(1, baudrate=80000000, polarity=0, phase=0)
|
||||
|
||||
(``SPI(0)`` is used for FlashROM and not available to users.)
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
|
||||
@@ -239,15 +255,14 @@ The OneWire driver is implemented in software and works on all pins::
|
||||
ow.scan() # return a list of devices on the bus
|
||||
ow.reset() # reset the bus
|
||||
ow.readbyte() # read a byte
|
||||
ow.read(5) # read 5 bytes
|
||||
ow.writebyte(0x12) # write a byte on the bus
|
||||
ow.write('123') # write bytes on the bus
|
||||
ow.select_rom(b'12345678') # select a specific device by its ROM code
|
||||
|
||||
There is a specific driver for DS18B20 devices::
|
||||
There is a specific driver for DS18S20 and DS18B20 devices::
|
||||
|
||||
import time
|
||||
ds = onewire.DS18B20(ow)
|
||||
import time, ds18x20
|
||||
ds = ds18x20.DS18X20(ow)
|
||||
roms = ds.scan()
|
||||
ds.convert_temp()
|
||||
time.sleep_ms(750)
|
||||
@@ -321,29 +336,27 @@ WebREPL (web browser interactive prompt)
|
||||
WebREPL (REPL over WebSockets, accessible via a web browser) is an
|
||||
experimental feature available in ESP8266 port. Download web client
|
||||
from https://github.com/micropython/webrepl (hosted version available
|
||||
at http://micropython.org/webrepl), and start the daemon on a device
|
||||
using::
|
||||
at http://micropython.org/webrepl), and configure it by executing::
|
||||
|
||||
import webrepl_setup
|
||||
|
||||
and following on-screen instructions. After reboot, it will be available
|
||||
for connection. If you disabled automatic start-up on boot, you may
|
||||
run configured daemon on demand using::
|
||||
|
||||
import webrepl
|
||||
webrepl.start()
|
||||
|
||||
(Release versions have it started on boot by default.)
|
||||
|
||||
On a first connection, you will be prompted to set password for future
|
||||
sessions to use.
|
||||
|
||||
The supported way to use WebREPL is by connecting to ESP8266 access point,
|
||||
but the daemon is also started on STA interface if it is active, so if your
|
||||
router is set up and works correctly, you may also use WebREPL while connected
|
||||
to your normal Internet access point (use the ESP8266 AP connection method
|
||||
if you face any issues).
|
||||
|
||||
WebREPL is an experimental feature and a work in progress, and has known
|
||||
issues.
|
||||
Besides terminal/command prompt access, WebREPL also has provision for file
|
||||
transfer (both upload and download). Web client has buttons for the
|
||||
corresponding functions, or you can use command-line client ``webrepl_cli.py``
|
||||
from the repository above.
|
||||
|
||||
There's also provision to transfer (both upload and download)
|
||||
files over WebREPL connection, but it has even more experimental status
|
||||
than the WebREPL terminal mode. It is still a practical way to
|
||||
get script files onto ESP8266, so give it a try using ``webrepl_cli.py``
|
||||
from the repository above. See the MicroPython forum for other
|
||||
community-supported alternatives to transfer files to ESP8266.
|
||||
See the MicroPython forum for other community-supported alternatives
|
||||
to transfer files to ESP8266.
|
||||
|
||||
@@ -64,7 +64,6 @@ device starts up.
|
||||
Accessing the filesystem via WebREPL
|
||||
------------------------------------
|
||||
|
||||
You can access the filesystem over WebREPL using the provided command-line
|
||||
tool. This tool is found at `<https://github.com/micropython/webrepl>`__
|
||||
and is called webrepl_cli.py. Please refer to that program for information
|
||||
on how to use it.
|
||||
You can access the filesystem over WebREPL using the web client in a browser
|
||||
or via the command-line tool. Please refer to Quick Reference and Tutorial
|
||||
sections for more information about WebREPL.
|
||||
|
||||
@@ -35,11 +35,30 @@ If your board has a USB connector on it then most likely it is powered through
|
||||
this when connected to your PC. Otherwise you will need to power it directly.
|
||||
Please refer to the documentation for your board for further details.
|
||||
|
||||
Getting the firmware
|
||||
--------------------
|
||||
|
||||
The first thing you need to do is download the most recent MicroPython firmware
|
||||
.bin file to load onto your ESP8266 device. You can download it from the
|
||||
`MicroPython downloads page <http://micropython.org/download#esp8266>`_.
|
||||
From here, you have 3 main choices
|
||||
|
||||
* Stable firmware builds for 1024kb modules and above.
|
||||
* Daily firmware builds for 1024kb modules and above.
|
||||
* Daily firmware builds for 512kb modules.
|
||||
|
||||
The best bet is nearly always to go for the Stable firmware builds.
|
||||
An exception to this though is if you have an ESP8266 module with only 512kb
|
||||
of onboard storage. You can easily tell by trying to load a Stable firmware
|
||||
build and if you get the error below, then you may have to use the Daily
|
||||
firmware builds for 512kb modules.
|
||||
WARNING: Unlikely to work as data goes beyond end of flash.
|
||||
|
||||
Deploying the firmware
|
||||
----------------------
|
||||
|
||||
The very first thing you need to do is put the MicroPython firmware (compiled
|
||||
code) on your ESP8266 device. There are two main steps to do this: first you
|
||||
Once you have the MicroPython firmware (compiled code), you need to load it onto
|
||||
your ESP8266 device. There are two main steps to do this: first you
|
||||
need to put your device in boot-loader mode, and second you need to copy across
|
||||
the firmware. The exact procedure for these steps is highly dependent on the
|
||||
particular board and you will need to refer to its documentation for details.
|
||||
@@ -54,7 +73,7 @@ device before putting on new MicroPython firmware.
|
||||
|
||||
Currently we only support esptool.py to copy across the firmware. You can find
|
||||
this tool here: `<https://github.com/themadinventor/esptool/>`__, or install it
|
||||
using pip::
|
||||
using pip (at least version 1.2.1 is required)::
|
||||
|
||||
pip install esptool
|
||||
|
||||
@@ -69,7 +88,7 @@ Using esptool.py you can erase the flash with the command::
|
||||
|
||||
And then deploy the new firmware using::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 esp8266-2016-05-03-v1.8.bin
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
You might need to change the "port" setting to something else relevant for your
|
||||
PC. You may also need to reduce the baudrate if you get errors when flashing
|
||||
@@ -80,7 +99,7 @@ For some boards with a particular FlashROM configuration (e.g. some variants of
|
||||
a NodeMCU board) you may need to use the following command to deploy
|
||||
the firmware (note the ``-fm dio`` option)::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
If the above commands run without error then MicroPython should be installed on
|
||||
your board!
|
||||
@@ -135,6 +154,12 @@ after it, here are troubleshooting recommendations:
|
||||
rate may be too high and lead to errors. Try a more common 115200 baud
|
||||
rate instead in such cases.
|
||||
|
||||
* If lower baud rate didn't help, you may want to try older version of
|
||||
esptool.py, which had a different programming algorithm::
|
||||
pip install esptool==1.0.1
|
||||
This version doesn't support ``--flash_size=detect`` option, so you will
|
||||
need to specify FlashROM size explicitly (in megabits).
|
||||
|
||||
* The ``--flash_size`` option in the commands above is mandatory. Omitting
|
||||
it will lead to a corrupted firmware.
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ Let's define a function that can download and print a URL::
|
||||
print(str(data, 'utf8'), end='')
|
||||
else:
|
||||
break
|
||||
s.close()
|
||||
|
||||
Make sure that you import the socket module before running this function. Then
|
||||
you can try::
|
||||
|
||||
@@ -6,19 +6,19 @@ The 1-wire bus is a serial bus that uses just a single wire for communication
|
||||
is a very popular 1-wire device, and here we show how to use the onewire module
|
||||
to read from such a device.
|
||||
|
||||
For the following code to work you need to have at least one DS18B20 temperature
|
||||
For the following code to work you need to have at least one DS18S20 or DS18B20 temperature
|
||||
sensor with its data line connected to GPIO12. You must also power the sensors
|
||||
and connect a 4.7k Ohm resistor between the data pin and the power pin. ::
|
||||
|
||||
import time
|
||||
import machine
|
||||
import onewire
|
||||
import onewire, ds18x20
|
||||
|
||||
# the device is on GPIO12
|
||||
dat = machine.Pin(12)
|
||||
|
||||
# create the onewire object
|
||||
ds = onewire.DS18B20(onewire.OneWire(dat))
|
||||
ds = ds18x20.DS18X20(onewire.OneWire(dat))
|
||||
|
||||
# scan for devices on the bus
|
||||
roms = ds.scan()
|
||||
|
||||
@@ -14,7 +14,7 @@ Here, the "0" is the pin that you want to access. Usually you want to
|
||||
configure the pin to be input or output, and you do this when constructing
|
||||
it. To make an input pin use::
|
||||
|
||||
>>> pin = machine.Pin(0, machine.Pin.OUT, machine.Pin.PULL_UP)
|
||||
>>> pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)
|
||||
|
||||
You can either use PULL_UP or None for the input pull-mode. If it's
|
||||
not specified then it defaults to None, which is no pull resistor.
|
||||
|
||||
@@ -41,6 +41,18 @@ For your convenience, WebREPL client is hosted at
|
||||
locally from the the GitHub repository
|
||||
`<https://github.com/micropython/webrepl>`__ .
|
||||
|
||||
Before connecting to WebREPL, you should set a password and enable it via
|
||||
a normal serial connection. Initial versions of MicroPython for ESP8266
|
||||
came with WebREPL automatically enabled on the boot and with the
|
||||
ability to set a password via WiFi on the first connection, but as WebREPL
|
||||
was becoming more widely known and popular, the initial setup has switched
|
||||
to a wired connection for improved security::
|
||||
|
||||
import webrepl_setup
|
||||
|
||||
Follow the on-screen instructions and prompts. To make any changes active,
|
||||
you will need to reboot your device.
|
||||
|
||||
To use WebREPL connect your computer to the ESP8266's access point
|
||||
(MicroPython-xxxxxx, see the previous section about this). If you have
|
||||
already reconfigured your ESP8266 to connect to a router then you can
|
||||
@@ -49,19 +61,11 @@ skip this part.
|
||||
Once you are on the same network as the ESP8266 you click the "Connect" button
|
||||
(if you are connecting via a router then you may need to change the IP address,
|
||||
by default the IP address is correct when connected to the ESP8266's access
|
||||
point). If the connection succeeds then you should see a welcome message.
|
||||
point). If the connection succeeds then you should see a password prompt.
|
||||
|
||||
On the first connection you need to set a password. Make sure that the
|
||||
terminal widget is selected by clicking on it, and then follow prompts to
|
||||
type in your password twice (they should match each other). Then ESP8266
|
||||
will then reboot with the password applied (the WiFi will go down but come
|
||||
back up again). Note that some modules may have troubles rebooting
|
||||
automatically and need reset button press or power cycle (do this if
|
||||
you don't see ESP8266 access point appearing in a minute or so).
|
||||
|
||||
You should then click the "Connect" button again, and enter your password
|
||||
to connect. If you type in the correct password you should get a prompt
|
||||
looking like ``>>>``. You can now start typing Python commands!
|
||||
Once you type the password configured at the setup step above, press Enter once
|
||||
more and you should get a prompt looking like ``>>>``. You can now start
|
||||
typing Python commands!
|
||||
|
||||
Using the REPL
|
||||
--------------
|
||||
|
||||
@@ -28,6 +28,11 @@ All builtin functions are described here. They are also available via
|
||||
|
||||
.. class:: complex()
|
||||
|
||||
.. function:: delattr(obj, name)
|
||||
|
||||
The argument *name* should be a string, and this function deletes the named
|
||||
attribute from the object given by *obj*.
|
||||
|
||||
.. class:: dict()
|
||||
|
||||
.. function:: dir()
|
||||
@@ -110,6 +115,10 @@ All builtin functions are described here. They are also available via
|
||||
|
||||
.. function:: setattr()
|
||||
|
||||
.. class:: slice()
|
||||
|
||||
The *slice* builtin is the type that slice objects have.
|
||||
|
||||
.. function:: sorted()
|
||||
|
||||
.. function:: staticmethod()
|
||||
|
||||
@@ -45,3 +45,39 @@ Functions
|
||||
.. function:: flash_write(byte_offset, bytes)
|
||||
|
||||
.. function:: flash_erase(sector_no)
|
||||
|
||||
.. function:: set_native_code_location(start, length)
|
||||
|
||||
Set the location that native code will be placed for execution after it is
|
||||
compiled. Native code is emitted when the ``@micropython.native``,
|
||||
``@micropython.viper`` and ``@micropython.asm_xtensa`` decorators are applied
|
||||
to a function. The ESP8266 must execute code from either iRAM or the lower
|
||||
1MByte of flash (which is memory mapped), and this function controls the
|
||||
location.
|
||||
|
||||
If `start` and `length` are both `None` then the native code location is
|
||||
set to the unused portion of memory at the end of the iRAM1 region. The
|
||||
size of this unused portion depends on the firmware and is typically quite
|
||||
small (around 500 bytes), and is enough to store a few very small
|
||||
functions. The advantage of using this iRAM1 region is that it does not
|
||||
get worn out by writing to it.
|
||||
|
||||
If neither `start` nor `length` are `None` then they should be integers.
|
||||
`start` should specify the byte offset from the beginning of the flash at
|
||||
which native code should be stored. `length` specifies how many bytes of
|
||||
flash from `start` can be used to store native code. `start` and `length`
|
||||
should be multiples of the sector size (being 4096 bytes). The flash will
|
||||
be automatically erased before writing to it so be sure to use a region of
|
||||
flash that is not otherwise used, for example by the firmware or the
|
||||
filesystem.
|
||||
|
||||
When using the flash to store native code `start+length` must be less
|
||||
than or equal to 1MByte. Note that the flash can be worn out if repeated
|
||||
erasures (and writes) are made so use this feature sparingly.
|
||||
In particular, native code needs to be recompiled and rewritten to flash
|
||||
on each boot (including wake from deepsleep).
|
||||
|
||||
In both cases above, using iRAM1 or flash, if there is no more room left
|
||||
in the specified region then the use of a native decorator on a function
|
||||
will lead to `MemoryError` exception being raised during compilation of
|
||||
that function.
|
||||
|
||||
@@ -36,23 +36,28 @@ Python standard libraries and micro-libraries
|
||||
The following standard Python libraries have been "micro-ified" to fit in with
|
||||
the philosophy of MicroPython. They provide the core functionality of that
|
||||
module and are intended to be a drop-in replacement for the standard Python
|
||||
library.
|
||||
library. Some modules below use a standard Python name, but prefixed with "u",
|
||||
e.g. ``ujson`` instead of ``json``. This is to signify that such a module is
|
||||
micro-library, i.e. implements only a subset of CPython module functionality.
|
||||
By naming them differently, a user has a choice to write a Python-level module
|
||||
to extend functionality for better compatibility with CPython (indeed, this is
|
||||
what done by micropython-lib project mentioned above).
|
||||
|
||||
.. only:: not port_unix
|
||||
|
||||
The modules are available by their u-name, and also by their non-u-name. The
|
||||
non-u-name can be overridden by a file of that name in your package path.
|
||||
For example, ``import json`` will first search for a file ``json.py`` or
|
||||
directory ``json`` and load that package if it is found. If nothing is found,
|
||||
it will fallback to loading the built-in ``ujson`` module.
|
||||
On some embedded platforms, where it may be cumbersome to add Python-level
|
||||
wrapper modules to achieve naming compatibility with CPython, micro-modules
|
||||
are available both by their u-name, and also by their non-u-name. The
|
||||
non-u-name can be overridden by a file of that name in your package path.
|
||||
For example, ``import json`` will first search for a file ``json.py`` or
|
||||
directory ``json`` and load that package if it is found. If nothing is found,
|
||||
it will fallback to loading the built-in ``ujson`` module.
|
||||
|
||||
.. only:: port_unix
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
@@ -76,8 +81,8 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
@@ -101,8 +106,8 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
gc.rst
|
||||
select.rst
|
||||
sys.rst
|
||||
@@ -119,8 +124,8 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
sys.rst
|
||||
|
||||
@@ -49,12 +49,23 @@ Constructors
|
||||
Construct an I2C object on the given bus. `bus` can only be 0.
|
||||
If the bus is not given, the default one will be selected (0).
|
||||
|
||||
.. only:: port_esp8266
|
||||
.. only:: not port_wipy
|
||||
|
||||
.. class:: I2C(scl, sda, \*, freq=400000)
|
||||
.. class:: I2C(id=-1, \*, scl, sda, freq=400000)
|
||||
|
||||
Construct and return a new I2C object.
|
||||
See the init method below for a description of the arguments.
|
||||
Construct and return a new I2C object using the following parameters:
|
||||
|
||||
- `id` identifies the particular I2C peripheral. The default
|
||||
value of -1 selects a software implementation of I2C which can
|
||||
work (in most cases) with arbitrary pins for SCL and SDA.
|
||||
If `id` is -1 then `scl` and `sda` must be specified. Other
|
||||
allowed values for `id` depend on the particular port/board,
|
||||
and specifying `scl` and `sda` may or may not be required or
|
||||
allowed in this case.
|
||||
- `scl` should be a pin object specifying the pin to use for SCL.
|
||||
- `sda` should be a pin object specifying the pin to use for SDA.
|
||||
- `freq` should be an integer which sets the maximum frequency
|
||||
for SCL.
|
||||
|
||||
General Methods
|
||||
---------------
|
||||
@@ -102,29 +113,31 @@ control over the bus, otherwise the standard methods (see below) can be used.
|
||||
|
||||
.. method:: I2C.start()
|
||||
|
||||
Send a start bit on the bus (SDA transitions to low while SCL is high).
|
||||
Generate a START condition on the bus (SDA transitions to low while SCL is high).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: I2C.stop()
|
||||
|
||||
Send a stop bit on the bus (SDA transitions to high while SCL is high).
|
||||
Generate a STOP condition on the bus (SDA transitions to high while SCL is high).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: I2C.readinto(buf)
|
||||
.. method:: I2C.readinto(buf, nack=True)
|
||||
|
||||
Reads bytes from the bus and stores them into `buf`. The number of bytes
|
||||
read is the length of `buf`. An ACK will be sent on the bus after
|
||||
receiving all but the last byte, and a NACK will be sent following the last
|
||||
byte.
|
||||
receiving all but the last byte. After the last byte is received, if `nack`
|
||||
is true then a NACK will be sent, otherwise an ACK will be sent (and in this
|
||||
case the slave assumes more bytes are going to be read in a later call).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: I2C.write(buf)
|
||||
|
||||
Write all the bytes from `buf` to the bus. Checks that an ACK is received
|
||||
after each byte and raises an OSError if not.
|
||||
Write the bytes from `buf` to the bus. Checks that an ACK is received
|
||||
after each byte and stops transmitting the remaining bytes if a NACK is
|
||||
received. The function returns the number of ACKs that were received.
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
@@ -134,29 +147,27 @@ Standard bus operations
|
||||
The following methods implement the standard I2C master read and write
|
||||
operations that target a given slave device.
|
||||
|
||||
.. method:: I2C.readfrom(addr, nbytes)
|
||||
.. method:: I2C.readfrom(addr, nbytes, stop=True)
|
||||
|
||||
Read `nbytes` from the slave specified by `addr`.
|
||||
If `stop` is true then a STOP condition is generated at the end of the transfer.
|
||||
Returns a `bytes` object with the data read.
|
||||
|
||||
.. method:: I2C.readfrom_into(addr, buf)
|
||||
.. method:: I2C.readfrom_into(addr, buf, stop=True)
|
||||
|
||||
Read into `buf` from the slave specified by `addr`.
|
||||
The number of bytes read will be the length of `buf`.
|
||||
If `stop` is true then a STOP condition is generated at the end of the transfer.
|
||||
|
||||
On WiPy the return value is the number of bytes read. Otherwise the
|
||||
return value is `None`.
|
||||
The method returns `None`.
|
||||
|
||||
.. method:: I2C.writeto(addr, buf, \*, stop=True)
|
||||
.. method:: I2C.writeto(addr, buf, stop=True)
|
||||
|
||||
Write the bytes from `buf` to the slave specified by `addr`.
|
||||
|
||||
The `stop` argument (only available on WiPy) tells if a stop bit should be
|
||||
sent at the end of the transfer. If `False` the transfer should be
|
||||
continued later on.
|
||||
|
||||
On WiPy the return value is the number of bytes written. Otherwise the
|
||||
return value is `None`.
|
||||
Write the bytes from `buf` to the slave specified by `addr`. If a
|
||||
NACK is received following the write of a byte from `buf` then the
|
||||
remaining bytes are not sent. If `stop` is true then a STOP condition is
|
||||
generated at the end of the transfer, even if a NACK is received.
|
||||
The function returns the number of ACKs that were received.
|
||||
|
||||
Memory operations
|
||||
-----------------
|
||||
@@ -170,8 +181,7 @@ methods are convenience functions to communicate with such devices.
|
||||
|
||||
Read `nbytes` from the slave specified by `addr` starting from the memory
|
||||
address specified by `memaddr`.
|
||||
The argument `addrsize` specifies the address size in bits (on ESP8266
|
||||
this argument is not recognised and the address size is always 8 bits).
|
||||
The argument `addrsize` specifies the address size in bits.
|
||||
Returns a `bytes` object with the data read.
|
||||
|
||||
.. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8)
|
||||
|
||||
@@ -3,16 +3,44 @@
|
||||
class Pin -- control I/O pins
|
||||
=============================
|
||||
|
||||
A pin is the basic object to control I/O pins (also known as GPIO -
|
||||
general-purpose input/output). It has methods to set
|
||||
the mode of the pin (input, output, etc) and methods to get and set the
|
||||
digital logic level. For analog control of a pin, see the ADC class.
|
||||
A pin object is used to control I/O pins (also known as GPIO - general-purpose
|
||||
input/output). Pin objects are commonly associated with a physical pin that can
|
||||
drive an output voltage and read input voltages. The pin class has methods to set the mode of
|
||||
the pin (IN, OUT, etc) and methods to get and set the digital logic level.
|
||||
For analog control of a pin, see the :class:`ADC` class.
|
||||
|
||||
Usage Model:
|
||||
A pin object is constructed by using an identifier which unambiguously
|
||||
specifies a certain I/O pin. The allowed forms of the identifier and the
|
||||
physical pin that the identifier maps to are port-specific. Possibilities
|
||||
for the identifier are an integer, a string or a tuple with port and pin
|
||||
number.
|
||||
|
||||
Usage Model::
|
||||
|
||||
from machine import Pin
|
||||
|
||||
# create an output pin on pin #0
|
||||
p0 = Pin(0, Pin.OUT)
|
||||
|
||||
# set the value low then high
|
||||
p0.value(0)
|
||||
p0.value(1)
|
||||
|
||||
# create an input pin on pin #2, with a pull up resistor
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
|
||||
# read and print the pin value
|
||||
print(p2.value())
|
||||
|
||||
# reconfigure pin #0 in input mode
|
||||
p0.mode(p0.IN)
|
||||
|
||||
# configure an irq callback
|
||||
p0.irq(lambda p:print(p))
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
Board pins are identified by their string id::
|
||||
On the WiPy board the pins are identified by their string id::
|
||||
|
||||
from machine import Pin
|
||||
g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
|
||||
@@ -40,174 +68,224 @@ Usage Model:
|
||||
All pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins.
|
||||
|
||||
.. only:: port_esp8266
|
||||
For the ``drive`` parameter the strengths are:
|
||||
|
||||
::
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
|
||||
from machine import Pin
|
||||
For the ``alt`` parameter please refer to the pinout and alternate functions
|
||||
table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
|
||||
# create an output pin on GPIO0
|
||||
p0 = Pin(0, Pin.OUT)
|
||||
p0.value(0)
|
||||
p0.value(1)
|
||||
For interrupts, the ``priority`` can take values in the range 1-7. And the
|
||||
``wake`` parameter has the following properties:
|
||||
|
||||
# create an input pin on GPIO2
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
print(p2.value())
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: Pin(id, ...)
|
||||
.. class:: Pin(id, mode=-1, pull=-1, \*, value, drive, alt)
|
||||
|
||||
Create a new Pin object associated with the id. If additional arguments are given,
|
||||
they are used to initialise the pin. See :meth:`Pin.init`.
|
||||
Access the pin peripheral (GPIO pin) associated with the given ``id``. If
|
||||
additional arguments are given in the constructor then they are used to initialise
|
||||
the pin. Any settings that are not specified will remain in their previous state.
|
||||
|
||||
The arguments are:
|
||||
|
||||
- ``id`` is mandatory and can be an arbitrary object. Among possible value
|
||||
types are: int (an internal Pin identifier), str (a Pin name), and tuple
|
||||
(pair of [port, pin]).
|
||||
|
||||
- ``mode`` specifies the pin mode, which can be one of:
|
||||
|
||||
- ``Pin.IN`` - Pin is configured for input. If viewed as an output the pin
|
||||
is in high-impedance state.
|
||||
|
||||
- ``Pin.OUT`` - Pin is configured for (normal) output.
|
||||
|
||||
- ``Pin.OPEN_DRAIN`` - Pin is configured for open-drain output. Open-drain
|
||||
output works in the following way: if the output value is set to 0 the pin
|
||||
is active at a low level; if the output value is 1 the pin is in a high-impedance
|
||||
state. Not all ports implement this mode, or some might only on certain pins.
|
||||
|
||||
- ``Pin.ALT`` - Pin is configured to perform an alternative function, which is
|
||||
port specific. For a pin configured in such a way any other Pin methods
|
||||
(except :meth:`Pin.init`) are not applicable (calling them will lead to undefined,
|
||||
or a hardware-specific, result). Not all ports implement this mode.
|
||||
|
||||
- ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as
|
||||
open-drain. Not all ports implement this mode.
|
||||
|
||||
- ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be
|
||||
one of:
|
||||
|
||||
- ``None`` - No pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - Pull up resistor enabled.
|
||||
- ``Pin.PULL_DOWN`` - Pull down resistor enabled.
|
||||
|
||||
- ``value`` is valid only for Pin.OUT and Pin.OPEN_DRAIN modes and specifies initial
|
||||
output pin value if given, otherwise the state of the pin peripheral remains
|
||||
unchanged.
|
||||
|
||||
- ``drive`` specifies the output power of the pin and can be one of: ``Pin.LOW_POWER``,
|
||||
``Pin.MED_POWER`` or ``Pin.HIGH_POWER``. The actual current driving capabilities
|
||||
are port dependent. Not all ports implement this argument.
|
||||
|
||||
- ``alt`` specifies an alternate function for the pin and the values it can take are
|
||||
port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN``
|
||||
modes. It may be used when a pin supports more than one alternate function. If only
|
||||
one pin alternate function is supported the this argument is not required. Not all
|
||||
ports implement this argument.
|
||||
|
||||
As specified above, the Pin class allows to set an alternate function for a particular
|
||||
pin, but it does not specify any further operations on such a pin. Pins configured in
|
||||
alternate-function mode are usually not used as GPIO but are instead driven by other
|
||||
hardware peripherals. The only operation supported on such a pin is re-initialising,
|
||||
by calling the constructor or :meth:`Pin.init` method. If a pin that is configured in
|
||||
alternate-function mode is re-initialised with ``Pin.IN``, ``Pin.OUT``, or
|
||||
``Pin.OPEN_DRAIN``, the alternate function will be removed from the pin.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. only:: port_wipy
|
||||
.. method:: Pin.init(mode=-1, pull=-1, \*, value, drive, alt)
|
||||
|
||||
.. method:: Pin.init(mode, pull, \*, drive, alt)
|
||||
|
||||
Initialise the pin:
|
||||
Re-initialise the pin using the given parameters. Only those arguments that
|
||||
are specified will be set. The rest of the pin peripheral state will remain
|
||||
unchanged. See the constructor documentation for details of the arguments.
|
||||
|
||||
- ``mode`` can be one of:
|
||||
Returns ``None``.
|
||||
|
||||
- ``Pin.IN`` - input pin.
|
||||
- ``Pin.OUT`` - output pin in push-pull mode.
|
||||
- ``Pin.OPEN_DRAIN`` - output pin in open-drain mode.
|
||||
- ``Pin.ALT`` - pin mapped to an alternate function.
|
||||
- ``Pin.ALT_OPEN_DRAIN`` - pin mapped to an alternate function in open-drain mode.
|
||||
.. method:: Pin.value([x])
|
||||
|
||||
- ``pull`` can be one of:
|
||||
This method allows to set and get the value of the pin, depending on whether
|
||||
the argument ``x`` is supplied or not.
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
- ``Pin.PULL_DOWN`` - pull down resistor enabled.
|
||||
If the argument is omitted then this method gets the digital logic level of
|
||||
the pin, returning 0 or 1 corresponding to low and high voltage signals
|
||||
respectively. The behaviour of this method depends on the mode of the pin:
|
||||
|
||||
- ``drive`` can be one of:
|
||||
- ``Pin.IN`` - The method returns the actual input value currently present
|
||||
on the pin.
|
||||
- ``Pin.OUT`` - The behaviour and return value of the method is undefined.
|
||||
- ``Pin.OPEN_DRAIN`` - If the pin is in state '0' then the behaviour and
|
||||
return value of the method is undefined. Otherwise, if the pin is in
|
||||
state '1', the method returns the actual input value currently present
|
||||
on the pin.
|
||||
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
If the argument is supplied then this method sets the digital logic level of
|
||||
the pin. The argument ``x`` can be anything that converts to a boolean.
|
||||
If it converts to ``True``, the pin is set to state '1', otherwise it is set
|
||||
to state '0'. The behaviour of this method depends on the mode of the pin:
|
||||
|
||||
- ``alt`` is the number of the alternate function. Please refer to the
|
||||
`pinout and alternate functions table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
- ``Pin.IN`` - The value is stored in the output buffer for the pin. The
|
||||
pin state does not change, it remains in the high-impedance state. The
|
||||
stored value will become active on the pin as soon as it is changed to
|
||||
``Pin.OUT`` or ``Pin.OPEN_DRAIN`` mode.
|
||||
- ``Pin.OUT`` - The output buffer is set to the given value immediately.
|
||||
- ``Pin.OPEN_DRAIN`` - If the value is '0' the pin is set to a low voltage
|
||||
state. Otherwise the pin is set to high-impedance state.
|
||||
|
||||
Returns: ``None``.
|
||||
When setting the value this method returns ``None``.
|
||||
|
||||
.. method:: Pin.id()
|
||||
.. method:: Pin.out_value()
|
||||
|
||||
Get the pin id.
|
||||
Return the value stored in the output buffer of a pin, regardless of its mode.
|
||||
|
||||
.. only:: port_esp8266
|
||||
Not all ports implement this method.
|
||||
|
||||
.. method:: Pin.init(mode, pull=None, \*, value)
|
||||
.. method:: Pin.__call__([x])
|
||||
|
||||
Initialise the pin:
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set
|
||||
and get the value of the pin. It is equivalent to Pin.value([x]).
|
||||
See :meth:`Pin.value` for more details.
|
||||
|
||||
- `mode` can be one of:
|
||||
.. method:: Pin.toggle()
|
||||
|
||||
- ``Pin.IN`` - input pin.
|
||||
- ``Pin.OUT`` - output pin in push-pull mode.
|
||||
Toggle the output value of the pin. Equivalent to ``pin.value(not pin.out_value())``.
|
||||
Returns ``None``.
|
||||
|
||||
- `pull` can be one of:
|
||||
Not all ports implement this method.
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
Availability: WiPy.
|
||||
|
||||
- if `value` is given then it is the output value to set the pin
|
||||
if it is in output mode.
|
||||
.. method:: Pin.id()
|
||||
|
||||
.. method:: Pin.value([value])
|
||||
Get the pin identifier. This may return the ``id`` as specified in the
|
||||
constructor. Or it may return a canonical software-specific pin id.
|
||||
|
||||
Get or set the digital logic level of the pin:
|
||||
.. method:: Pin.mode([mode])
|
||||
|
||||
- With no argument, return 0 or 1 depending on the logic level of the pin.
|
||||
- With ``value`` given, set the logic level of the pin. ``value`` can be
|
||||
anything that converts to a boolean. If it converts to ``True``, the pin
|
||||
is set high, otherwise it is set low.
|
||||
Get or set the pin mode.
|
||||
See the constructor documentation for details of the ``mode`` argument.
|
||||
|
||||
.. method:: Pin.__call__([value])
|
||||
.. method:: Pin.pull([pull])
|
||||
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin.
|
||||
See :func:`Pin.value` for more details.
|
||||
Get or set the pin pull state.
|
||||
See the constructor documentation for details of the ``pull`` argument.
|
||||
|
||||
.. method:: Pin.alt_list()
|
||||
.. method:: Pin.drive([drive])
|
||||
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
Get or set the pin drive strength.
|
||||
See the constructor documentation for details of the ``drive`` argument.
|
||||
|
||||
Availability: WiPy.
|
||||
Not all ports implement this method.
|
||||
|
||||
Availability: WiPy.
|
||||
|
||||
.. method:: Pin.irq(handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), \*, priority=1, wake=None)
|
||||
|
||||
Configure an interrupt handler to be called when the trigger source of the
|
||||
pin is active. If the pin mode is ``Pin.IN`` then the trigger source is
|
||||
the external value on the pin. If the pin mode is ``Pin.OUT`` then the
|
||||
trigger source is the output buffer of the pin. Otherwise, if the pin mode
|
||||
is ``Pin.OPEN_DRAIN`` then the trigger source is the output buffer for
|
||||
state '0' and the external pin value for state '1'.
|
||||
|
||||
The arguments are:
|
||||
|
||||
- ``handler`` is an optional function to be called when the interrupt
|
||||
triggers.
|
||||
|
||||
- ``trigger`` configures the event which can generate an interrupt.
|
||||
Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level.
|
||||
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level.
|
||||
|
||||
These values can be OR'ed together to trigger on multiple events.
|
||||
|
||||
- ``priority`` sets the priority level of the interrupt. The values it
|
||||
can take are port-specific, but higher values always represent higher
|
||||
priorities.
|
||||
|
||||
- ``wake`` selects the power mode in which this interrupt can wake up the
|
||||
system. It can be ``machine.IDLE``, ``machine.SLEEP`` or ``machine.DEEPSLEEP``.
|
||||
These values can also be OR'ed together to make a pin generate interrupts in
|
||||
more than one power mode.
|
||||
|
||||
This method returns a callback object.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. method:: Pin.toggle()
|
||||
.. method:: Pin.alt_list()
|
||||
|
||||
Toggle the value of the pin.
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
|
||||
.. method:: Pin.mode([mode])
|
||||
Availability: WiPy.
|
||||
|
||||
Get or set the pin mode.
|
||||
|
||||
.. method:: Pin.pull([pull])
|
||||
|
||||
Get or set the pin pull.
|
||||
|
||||
.. method:: Pin.drive([drive])
|
||||
|
||||
Get or set the pin drive strength.
|
||||
|
||||
.. method:: Pin.irq(\*, trigger, priority=1, handler=None, wake=None)
|
||||
|
||||
Create a callback to be triggered when the input level at the pin changes.
|
||||
|
||||
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level.
|
||||
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level.
|
||||
|
||||
The values can be *ORed* together, for instance mode=Pin.IRQ_FALLING | Pin.IRQ_RISING
|
||||
|
||||
- ``priority`` level of the interrupt. Can take values in the range 1-7.
|
||||
Higher values represent higher priorities.
|
||||
- ``handler`` is an optional function to be called when new characters arrive.
|
||||
- ``wakes`` selects the power mode in which this interrupt can wake up the
|
||||
board. Please note:
|
||||
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
- Values can be ORed to make a pin generate interrupts in more than one power
|
||||
mode.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. method:: Pin.irq(\*, trigger, handler=None)
|
||||
|
||||
Create a callback to be triggered when the input level at the pin changes.
|
||||
|
||||
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
|
||||
The values can be OR'ed together to trigger on multiple events.
|
||||
|
||||
- ``handler`` is an optional function to be called when the interrupt triggers.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
@@ -239,7 +317,8 @@ not all constants are available on all ports.
|
||||
.. data:: Pin.PULL_UP
|
||||
Pin.PULL_DOWN
|
||||
|
||||
Selects the whether there is a pull up/down resistor.
|
||||
Selects whether there is a pull up/down resistor. Use the value
|
||||
``None`` for no pull.
|
||||
|
||||
.. data:: Pin.LOW_POWER
|
||||
Pin.MED_POWER
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
.. currentmodule:: machine
|
||||
|
||||
class SPI -- a master-driven serial protocol
|
||||
============================================
|
||||
class SPI -- a Serial Peripheral Interface bus protocol (master side)
|
||||
=====================================================================
|
||||
|
||||
SPI is a serial protocol that is driven by a master. At the physical level
|
||||
there are 3 lines: SCK, MOSI, MISO.
|
||||
SPI is a synchronous serial protocol that is driven by a master. At the
|
||||
physical level, a bus consists of 3 lines: SCK, MOSI, MISO. Multiple devices
|
||||
can share the same bus. Each device should have a separate, 4th signal,
|
||||
SS (Slave Select), to select a particualr device on a bus with which
|
||||
communication takes place. Management of an SS signal should happen in
|
||||
user code (via machine.Pin class).
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
@@ -21,65 +25,84 @@ there are 3 lines: SCK, MOSI, MISO.
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. only:: port_wipy
|
||||
.. class:: SPI(id, ...)
|
||||
|
||||
.. class:: SPI(id, ...)
|
||||
Construct an SPI object on the given bus, ``id``. Values of ``id`` depend
|
||||
on a particular port and its hardware. Values 0, 1, etc. are commonly used
|
||||
to select hardware SPI block #0, #1, etc. Value -1 can be used for
|
||||
bitbanging (software) implementation of SPI (if supported by a port).
|
||||
|
||||
Construct an SPI object on the given bus. ``id`` can be only 0.
|
||||
With no additional parameters, the SPI object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
With no additional parameters, the SPI object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: SPI.init(mode, baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, pins=(CLK, MOSI, MISO))
|
||||
.. method:: SPI.init(baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=None, mosi=None, miso=None, pins=(SCK, MOSI, MISO))
|
||||
|
||||
Initialise the SPI bus with the given parameters:
|
||||
|
||||
- ``mode`` must be ``SPI.MASTER``.
|
||||
- ``baudrate`` is the SCK clock rate.
|
||||
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at.
|
||||
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
|
||||
respectively.
|
||||
- ``bits`` is the width of each transfer, accepted values are 8, 16 and 32.
|
||||
- ``firstbit`` can be ``SPI.MSB`` only.
|
||||
- ``pins`` is an optional tuple with the pins to assign to the SPI bus.
|
||||
- ``bits`` is the width in bits of each transfer. Only 8 is guaranteed to be supported by all hardware.
|
||||
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``.
|
||||
- ``sck``, ``mosi``, ``miso`` are pins (machine.Pin) objects to use for bus signals. For most
|
||||
hardware SPI blocks (as selected by ``id`` parameter to the constructore), pins are fixed
|
||||
and cannot be changed. In some cases, hardware blocks allow 2-3 alternative pin sets for
|
||||
a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver
|
||||
(``id`` = -1).
|
||||
- ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to
|
||||
specify them as a tuple of ``pins`` paramter.
|
||||
|
||||
.. method:: SPI.deinit()
|
||||
|
||||
Turn off the SPI bus.
|
||||
|
||||
.. method:: SPI.read(nbytes, write=0x00)
|
||||
|
||||
Read a number of bytes specified by ``nbytes`` while continuously writing
|
||||
the single byte given by ``write``.
|
||||
Returns a ``bytes`` object with the data that was read.
|
||||
|
||||
.. method:: SPI.readinto(buf, write=0x00)
|
||||
|
||||
Read into the buffer specified by ``buf`` while continuously writing the
|
||||
single byte given by ``write``.
|
||||
Returns ``None``.
|
||||
|
||||
Note: on WiPy this function returns the number of bytes read.
|
||||
|
||||
.. method:: SPI.write(buf)
|
||||
|
||||
Write the data contained in ``buf``.
|
||||
Returns the number of bytes written.
|
||||
Write the bytes contained in ``buf``.
|
||||
Returns ``None``.
|
||||
|
||||
.. method:: SPI.read(nbytes, *, write=0x00)
|
||||
|
||||
Read the ``nbytes`` while writing the data specified by ``write``.
|
||||
Return the number of bytes read.
|
||||
|
||||
.. method:: SPI.readinto(buf, *, write=0x00)
|
||||
|
||||
Read into the buffer specified by ``buf`` while writing the data specified by
|
||||
``write``.
|
||||
Return the number of bytes read.
|
||||
Note: on WiPy this function returns the number of bytes written.
|
||||
|
||||
.. method:: SPI.write_readinto(write_buf, read_buf)
|
||||
|
||||
Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the
|
||||
Write the bytes from ``write_buf`` while reading into ``read_buf``. The
|
||||
buffers can be the same or different, but both buffers must have the
|
||||
same length.
|
||||
Returns the number of bytes written
|
||||
Returns ``None``.
|
||||
|
||||
Note: on WiPy this function returns the number of bytes written.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: SPI.MASTER
|
||||
|
||||
for initialising the SPI bus to master
|
||||
for initialising the SPI bus to master; this is only used for the WiPy
|
||||
|
||||
.. data:: SPI.MSB
|
||||
|
||||
set the first bit to be the most significant bit
|
||||
|
||||
.. data:: SPI.LSB
|
||||
|
||||
set the first bit to be the least significant bit
|
||||
|
||||
@@ -31,7 +31,7 @@ A UART object acts like a stream object and reading and writing is done
|
||||
using the standard stream methods::
|
||||
|
||||
uart.read(10) # read 10 characters, returns a bytes object
|
||||
uart.readall() # read all available characters
|
||||
uart.read() # read all available characters
|
||||
uart.readline() # read a line
|
||||
uart.readinto(buf) # read and store into the given buffer
|
||||
uart.write('abc') # write the 3 characters
|
||||
@@ -95,17 +95,12 @@ Methods
|
||||
|
||||
.. method:: UART.read([nbytes])
|
||||
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes,
|
||||
otherwise read as much data as possible.
|
||||
|
||||
Return value: a bytes object containing the bytes read in. Returns ``None``
|
||||
on timeout.
|
||||
|
||||
.. method:: UART.readall()
|
||||
|
||||
Read as much data as possible.
|
||||
|
||||
Return value: a bytes object or ``None`` on timeout.
|
||||
|
||||
.. method:: UART.readinto(buf[, nbytes])
|
||||
|
||||
Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
|
||||
|
||||
@@ -14,6 +14,8 @@ Example usage::
|
||||
wdt = WDT(timeout=2000) # enable it with a timeout of 2s
|
||||
wdt.feed()
|
||||
|
||||
Availability of this class: pyboard, WiPy.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
|
||||
@@ -24,17 +24,15 @@ Interrupt related functions
|
||||
.. function:: disable_irq()
|
||||
|
||||
Disable interrupt requests.
|
||||
Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs
|
||||
respectively. This return value can be passed to enable_irq to restore
|
||||
the IRQ to its original state.
|
||||
Returns the previous IRQ state which should be considered an opaque value.
|
||||
This return value should be passed to the ``enable_irq`` function to restore
|
||||
interrupts to their original state, before ``disable_irq`` was called.
|
||||
|
||||
.. function:: enable_irq(state=True)
|
||||
.. function:: enable_irq(state)
|
||||
|
||||
Enable interrupt requests.
|
||||
If ``state`` is ``True`` (the default value) then IRQs are enabled.
|
||||
If ``state`` is ``False`` then IRQs are disabled. The most common use of
|
||||
this function is to pass it the value returned by ``disable_irq`` to
|
||||
exit a critical section.
|
||||
Re-enable interrupt requests.
|
||||
The ``state`` parameter should be the value that was returned from the most
|
||||
recent call to the ``disable_irq`` function.
|
||||
|
||||
Power related functions
|
||||
-----------------------
|
||||
@@ -125,7 +123,7 @@ Constants
|
||||
|
||||
irq wake values
|
||||
|
||||
.. data:: machine.POWER_ON
|
||||
.. data:: machine.PWRON_RESET
|
||||
.. data:: machine.HARD_RESET
|
||||
.. data:: machine.WDT_RESET
|
||||
.. data:: machine.DEEPSLEEP_RESET
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
.. module:: network
|
||||
:synopsis: network configuration
|
||||
|
||||
This module provides network drivers and routing configuration. Network
|
||||
drivers for specific hardware are available within this module and are
|
||||
used to configure a hardware network interface. Configured interfaces
|
||||
are then available for use via the :mod:`socket` module. To use this module
|
||||
the network build of firmware must be installed.
|
||||
This module provides network drivers and routing configuration. To use this
|
||||
module, a MicroPython variant/build with network capabilities must be installed.
|
||||
Network drivers for specific hardware are available within this module and are
|
||||
used to configure hardware network interface(s). Network services provided
|
||||
by configured interfaces are then available for use via the :mod:`socket`
|
||||
module.
|
||||
|
||||
For example::
|
||||
|
||||
@@ -79,7 +80,7 @@ For example::
|
||||
class CC3K
|
||||
==========
|
||||
|
||||
This class provides a driver for CC3000 wifi modules. Example usage::
|
||||
This class provides a driver for CC3000 WiFi modules. Example usage::
|
||||
|
||||
import network
|
||||
nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3)
|
||||
@@ -128,16 +129,16 @@ For example::
|
||||
|
||||
.. method:: cc3k.connect(ssid, key=None, \*, security=WPA2, bssid=None)
|
||||
|
||||
Connect to a wifi access point using the given SSID, and other security
|
||||
Connect to a WiFi access point using the given SSID, and other security
|
||||
parameters.
|
||||
|
||||
.. method:: cc3k.disconnect()
|
||||
|
||||
Disconnect from the wifi access point.
|
||||
Disconnect from the WiFi access point.
|
||||
|
||||
.. method:: cc3k.isconnected()
|
||||
|
||||
Returns True if connected to a wifi access point and has a valid IP address,
|
||||
Returns True if connected to a WiFi access point and has a valid IP address,
|
||||
False otherwise.
|
||||
|
||||
.. method:: cc3k.ifconfig()
|
||||
@@ -323,7 +324,7 @@ For example::
|
||||
|
||||
.. method:: wlan.isconnected()
|
||||
|
||||
In case of STA mode, returns ``True`` if connected to a wifi access
|
||||
In case of STA mode, returns ``True`` if connected to a WiFi access
|
||||
point and has a valid IP address. In AP mode returns ``True`` when a
|
||||
station is connected. Returns ``False`` otherwise.
|
||||
|
||||
@@ -348,7 +349,7 @@ For example::
|
||||
|
||||
# Set WiFi access point name (formally known as ESSID) and WiFi channel
|
||||
ap.config(essid='My AP', channel=11)
|
||||
# Queey params one by one
|
||||
# Query params one by one
|
||||
print(ap.config('essid'))
|
||||
print(ap.config('channel'))
|
||||
|
||||
@@ -433,7 +434,7 @@ For example::
|
||||
|
||||
.. method:: wlan.connect(ssid, \*, auth=None, bssid=None, timeout=None)
|
||||
|
||||
Connect to a wifi access point using the given SSID, and other security
|
||||
Connect to a WiFi access point using the given SSID, and other security
|
||||
parameters.
|
||||
|
||||
- ``auth`` is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``,
|
||||
@@ -451,16 +452,16 @@ For example::
|
||||
|
||||
.. method:: wlan.disconnect()
|
||||
|
||||
Disconnect from the wifi access point.
|
||||
Disconnect from the WiFi access point.
|
||||
|
||||
.. method:: wlan.isconnected()
|
||||
|
||||
In case of STA mode, returns ``True`` if connected to a wifi access point and has a valid IP address.
|
||||
In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address.
|
||||
In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
|
||||
|
||||
.. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple])
|
||||
|
||||
With no parameters given eturns a 4-tuple of ``(ip, subnet_mask, gateway, DNS_server)``.
|
||||
With no parameters given returns a 4-tuple of ``(ip, subnet_mask, gateway, DNS_server)``.
|
||||
|
||||
if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
|
||||
are negotiated with the AP.
|
||||
@@ -498,10 +499,10 @@ For example::
|
||||
Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP``
|
||||
mode. Events are triggered by socket activity or by WLAN connection/disconnection.
|
||||
|
||||
- ``handler`` is the function that gets called when the irq is triggered.
|
||||
- ``handler`` is the function that gets called when the IRQ is triggered.
|
||||
- ``wake`` must be ``machine.SLEEP``.
|
||||
|
||||
Returns an irq object.
|
||||
Returns an IRQ object.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
@@ -46,3 +46,11 @@ Methods
|
||||
.. method:: Accel.z()
|
||||
|
||||
Get the z-axis value.
|
||||
|
||||
Hardware Note
|
||||
-------------
|
||||
|
||||
The accelerometer uses I2C bus 1 to communicate with the processor. Consequently
|
||||
when readings are being taken pins X9 and X10 should be unused (other than for
|
||||
I2C). Other devices using those pins, and which therefore cannot be used
|
||||
concurrently, are UART 1 and Timer 4 channels 1 and 2.
|
||||
|
||||
@@ -92,7 +92,7 @@ Methods
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. method:: I2C.init(mode, \*, addr=0x12, baudrate=400000, gencall=False)
|
||||
.. method:: I2C.init(mode, \*, addr=0x12, baudrate=400000, gencall=False, dma=False)
|
||||
|
||||
Initialise the I2C bus with the given parameters:
|
||||
|
||||
@@ -100,6 +100,9 @@ Methods
|
||||
- ``addr`` is the 7-bit address (only sensible for a slave)
|
||||
- ``baudrate`` is the SCL clock rate (only sensible for a master)
|
||||
- ``gencall`` is whether to support general call mode
|
||||
- ``dma`` is whether to allow the use of DMA for the I2C transfers (note
|
||||
that DMA transfers have more precise timing but currently do not handle bus
|
||||
errors properly)
|
||||
|
||||
.. method:: I2C.is_ready(addr)
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ Methods
|
||||
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at.
|
||||
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
|
||||
respectively.
|
||||
- ``bits`` can be 8 or 16, and is the number of bits in each transferred word.
|
||||
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``.
|
||||
- ``crc`` can be None for no CRC, or a polynomial specifier.
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ A UART object acts like a stream object and reading and writing is done
|
||||
using the standard stream methods::
|
||||
|
||||
uart.read(10) # read 10 characters, returns a bytes object
|
||||
uart.readall() # read all available characters
|
||||
uart.read() # read all available characters
|
||||
uart.readline() # read a line
|
||||
uart.readinto(buf) # read and store into the given buffer
|
||||
uart.write('abc') # write the 3 characters
|
||||
@@ -87,8 +87,8 @@ Methods
|
||||
- ``stop`` is the number of stop bits, 1 or 2.
|
||||
- ``flow`` sets the flow control type. Can be 0, ``UART.RTS``, ``UART.CTS``
|
||||
or ``UART.RTS | UART.CTS``.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the first character.
|
||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for writing/reading the first character.
|
||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters while writing or reading.
|
||||
- ``read_buf_len`` is the character length of the read buffer (0 to disable).
|
||||
|
||||
This method will raise an exception if the baudrate could not be set within
|
||||
@@ -111,17 +111,15 @@ Methods
|
||||
|
||||
Returns the number of bytes waiting (may be 0).
|
||||
|
||||
.. method:: UART.writechar(char)
|
||||
|
||||
Write a single character on the bus. ``char`` is an integer to write.
|
||||
Return value: ``None``. See note below if CTS flow control is used.
|
||||
|
||||
.. method:: UART.read([nbytes])
|
||||
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||
If ``nbytes`` are available in the buffer, returns immediately, otherwise returns
|
||||
when sufficient characters arrive or the timeout elapses.
|
||||
|
||||
If ``nbytes`` is not given then the method reads as much data as possible. It
|
||||
returns after the timeout has elapsed.
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
*Note:* for 9 bit characters each character takes two bytes, ``nbytes`` must
|
||||
@@ -130,12 +128,6 @@ Methods
|
||||
Return value: a bytes object containing the bytes read in. Returns ``None``
|
||||
on timeout.
|
||||
|
||||
.. method:: UART.readall()
|
||||
|
||||
Read as much data as possible. Returns after the timeout has elapsed.
|
||||
|
||||
Return value: a bytes object or ``None`` if timeout prevents any data being read.
|
||||
|
||||
.. method:: UART.readchar()
|
||||
|
||||
Receive a single character on the bus.
|
||||
@@ -170,6 +162,13 @@ Methods
|
||||
Return value: number of bytes written. If a timeout occurs and no bytes
|
||||
were written returns ``None``.
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. method:: UART.writechar(char)
|
||||
|
||||
Write a single character on the bus. ``char`` is an integer to write.
|
||||
Return value: ``None``. See note below if CTS flow control is used.
|
||||
|
||||
.. method:: UART.sendbreak()
|
||||
|
||||
Send a break condition on the bus. This drives the bus low for a duration
|
||||
|
||||
39
docs/library/pyb.USB_HID.rst
Normal file
39
docs/library/pyb.USB_HID.rst
Normal file
@@ -0,0 +1,39 @@
|
||||
.. currentmodule:: pyb
|
||||
|
||||
class USB_HID -- USB Human Interface Device (HID)
|
||||
=================================================
|
||||
|
||||
The USB_HID class allows creation of an object representing the USB
|
||||
Human Interface Device (HID) interface. It can be used to emulate
|
||||
a peripheral such as a mouse or keyboard.
|
||||
|
||||
Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the USB mode to include the HID interface.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.USB_HID()
|
||||
|
||||
Create a new USB_HID object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: USB_HID.recv(data, \*, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``data`` can be an integer, which is the number of bytes to receive,
|
||||
or a mutable buffer, which will be filled with received bytes.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: if ``data`` is an integer then a new buffer of the bytes received,
|
||||
otherwise the number of bytes read into ``data`` is returned.
|
||||
|
||||
.. method:: USB_HID.send(data)
|
||||
|
||||
Send data over the USB HID interface:
|
||||
|
||||
- ``data`` is the data to send (a tuple/list of integers, or a
|
||||
bytearray).
|
||||
@@ -44,16 +44,12 @@ Methods
|
||||
.. method:: USB_VCP.read([nbytes])
|
||||
|
||||
Read at most ``nbytes`` from the serial device and return them as a
|
||||
bytes object. If ``nbytes`` is not specified then the method acts as
|
||||
``readall()``. USB_VCP stream implicitly works in non-blocking mode,
|
||||
bytes object. If ``nbytes`` is not specified then the method reads
|
||||
all available bytes from the serial device.
|
||||
USB_VCP stream implicitly works in non-blocking mode,
|
||||
so if no pending data available, this method will return immediately
|
||||
with ``None`` value.
|
||||
|
||||
.. method:: USB_VCP.readall()
|
||||
|
||||
Read all available bytes from the serial device and return them as
|
||||
a bytes object, or ``None`` if no pending data available.
|
||||
|
||||
.. method:: USB_VCP.readinto(buf, [maxlen])
|
||||
|
||||
Read bytes from the serial device and store them into ``buf``, which
|
||||
|
||||
@@ -188,7 +188,7 @@ Miscellaneous functions
|
||||
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
|
||||
signal a HID mouse-motion event.
|
||||
|
||||
.. note:: This function is deprecated. Use pyb.USB_HID().send(...) instead.
|
||||
.. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead.
|
||||
|
||||
.. function:: info([dump_alloc_table])
|
||||
|
||||
@@ -254,6 +254,33 @@ Miscellaneous functions
|
||||
|
||||
Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU.
|
||||
|
||||
.. function:: usb_mode([modestr], vid=0xf055, pid=0x9801, hid=pyb.hid_mouse)
|
||||
|
||||
If called with no arguments, return the current USB mode as a string.
|
||||
|
||||
If called with ``modestr`` provided, attempts to set USB mode.
|
||||
This can only be done when called from ``boot.py`` before
|
||||
:meth:`pyb.main()` has been called. The following values of
|
||||
``modestr`` are understood:
|
||||
|
||||
- ``None``: disables USB
|
||||
- ``'VCP'``: enable with VCP (Virtual COM Port) interface
|
||||
- ``'VCP+MSC'``: enable with VCP and MSC (mass storage device class)
|
||||
- ``'VCP+HID'``: enable with VCP and HID (human interface device)
|
||||
|
||||
For backwards compatibility, ``'CDC'`` is understood to mean
|
||||
``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``).
|
||||
|
||||
The ``vid`` and ``pid`` parameters allow you to specify the VID
|
||||
(vendor id) and PID (product id).
|
||||
|
||||
If enabling HID mode, you may also specify the HID details by
|
||||
passing the ``hid`` keyword parameter. It takes a tuple of
|
||||
(subclass, protocol, max packet length, polling interval, report
|
||||
descriptor). By default it will set appropriate values for a USB
|
||||
mouse. There is also a ``pyb.hid_keyboard`` constant, which is an
|
||||
appropriate tuple for a USB keyboard.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
@@ -277,4 +304,5 @@ Classes
|
||||
pyb.Switch.rst
|
||||
pyb.Timer.rst
|
||||
pyb.UART.rst
|
||||
pyb.USB_HID.rst
|
||||
pyb.USB_VCP.rst
|
||||
|
||||
@@ -61,6 +61,29 @@ Functions
|
||||
|
||||
Get the status of a file or directory.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_esp8266
|
||||
|
||||
.. function:: statvfs(path)
|
||||
|
||||
Get the status of a fileystem.
|
||||
|
||||
Returns a tuple with the filesystem information in the following order:
|
||||
|
||||
* ``f_bsize`` -- file system block size
|
||||
* ``f_frsize`` -- fragment size
|
||||
* ``f_blocks`` -- size of fs in f_frsize units
|
||||
* ``f_bfree`` -- number of free blocks
|
||||
* ``f_bavail`` -- number of free blocks for unpriviliged users
|
||||
* ``f_files`` -- number of inodes
|
||||
* ``f_ffree`` -- number of free inodes
|
||||
* ``f_favail`` -- number of free inodes for unpriviliged users
|
||||
* ``f_flag`` -- mount flags
|
||||
* ``f_namemax`` -- maximum filename length
|
||||
|
||||
Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
|
||||
and the ``f_flags`` parameter may return ``0`` as they can be unavailable
|
||||
in a port-specific implementation.
|
||||
|
||||
.. function:: sync()
|
||||
|
||||
Sync all filesystems.
|
||||
|
||||
@@ -149,10 +149,18 @@ Methods
|
||||
|
||||
Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
|
||||
point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
|
||||
will raise a timeout exception if the timeout period value has elapsed before the operation has
|
||||
will raise an ``OSError`` exception if the timeout period value has elapsed before the operation has
|
||||
completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
|
||||
is put in blocking mode.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython raises a ``socket.timeout`` exception in case of timeout,
|
||||
which is an ``OSError`` subclass. MicroPython raises an OSError directly
|
||||
instead. If you use ``except OSError:`` to catch the exception,
|
||||
your code will work both in MicroPython and CPython.
|
||||
|
||||
.. method:: socket.setblocking(flag)
|
||||
|
||||
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
|
||||
@@ -178,14 +186,10 @@ Methods
|
||||
Closing the file object returned by makefile() WILL close the
|
||||
original socket as well.
|
||||
|
||||
.. method:: socket.read(size)
|
||||
.. method:: socket.read([size])
|
||||
|
||||
Read up to size bytes from the socket. Return a bytes object. If ``size`` is not given, it
|
||||
behaves just like ``socket.readall()``, see below.
|
||||
|
||||
.. method:: socket.readall()
|
||||
|
||||
Read all data available from the socket until ``EOF``. This function will not return until
|
||||
reads all data available from the socket until ``EOF``; as such the method will not return until
|
||||
the socket is closed.
|
||||
|
||||
.. method:: socket.readinto(buf[, nbytes])
|
||||
|
||||
@@ -82,37 +82,128 @@ Functions
|
||||
|
||||
.. function:: ticks_ms()
|
||||
|
||||
Returns an increasing millisecond counter with arbitrary reference point,
|
||||
that wraps after some (unspecified) value. The value should be treated as
|
||||
opaque, suitable for use only with ticks_diff().
|
||||
Returns an increasing millisecond counter with an arbitrary reference point,
|
||||
that wraps around after some value. This value is not explicitly exposed,
|
||||
but we will refer to it as `TICKS_MAX` to simplify discussion. Period of
|
||||
the values is `TICKS_PERIOD = TICKS_MAX + 1`. `TICKS_PERIOD` is guaranteed
|
||||
to be a power of two, but otherwise may differ from port to port. The same
|
||||
period value is used for all of ticks_ms(), ticks_us(), ticks_cpu() functions
|
||||
(for simplicity). Thus, these functions will return a value in range
|
||||
[0 .. `TICKS_MAX`], inclusive, total `TICKS_PERIOD` values. Note that only
|
||||
non-negative values are used. For the most part, you should treat values
|
||||
returned by these functions as opaque. The only operations available for them
|
||||
are ``ticks_diff()`` and ``ticks_add()`` functions described below.
|
||||
|
||||
Note: Performing standard mathematical operations (+, -) or relational
|
||||
operators (<, <=, >, >=) directly on these value will lead to invalid
|
||||
result. Performing mathematical operations and then passing their results
|
||||
as arguments to ``ticks_diff()`` or ``ticks_add()`` will also lead to
|
||||
invalid results from the latter functions.
|
||||
|
||||
.. function:: ticks_us()
|
||||
|
||||
Just like ``ticks_ms`` above, but in microseconds.
|
||||
|
||||
.. only:: port_wipy or port_pyboard
|
||||
.. function:: ticks_cpu()
|
||||
|
||||
.. function:: ticks_cpu()
|
||||
Similar to ``ticks_ms`` and ``ticks_us``, but with the highest possible resolution
|
||||
in the system. This is usually CPU clocks, and that's why the function is named that
|
||||
way. But it doesn't have to a CPU clock, some other timing source available in a
|
||||
system (e.g. high-resolution timer) can be used instead. The exact timing unit
|
||||
(resolution) of this function is not specified on ``utime`` module level, but
|
||||
documentation for a specific port may provide more specific information. This
|
||||
function is intended for very fine benchmarking or very tight real-time loops.
|
||||
Avoid using it in portable code.
|
||||
|
||||
Similar to ``ticks_ms`` and ``ticks_us``, but with higher resolution (usually CPU clocks).
|
||||
Availability: Not every port implements this function.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_wipy or port_esp8266
|
||||
|
||||
.. function:: ticks_diff(old, new)
|
||||
.. function:: ticks_add(ticks, delta)
|
||||
|
||||
Measure period between consecutive calls to ticks_ms(), ticks_us(), or ticks_cpu().
|
||||
The value returned by these functions may wrap around at any time, so directly
|
||||
subtracting them is not supported. ticks_diff() should be used instead. "old" value should
|
||||
actually precede "new" value in time, or result is undefined. This function should not be
|
||||
used to measure arbitrarily long periods of time (because ticks_*() functions wrap around
|
||||
and usually would have short period). The expected usage pattern is implementing event
|
||||
polling with timeout::
|
||||
Offset ticks value by a given number, which can be either positive or negative.
|
||||
Given a ``ticks`` value, this function allows to calculate ticks value ``delta``
|
||||
ticks before or after it, following modular-arithmetic definition of tick values
|
||||
(see ``ticks_ms()`` above). ``ticks`` parameter must be a direct result of call
|
||||
to ``tick_ms()``, ``ticks_us()``, ``ticks_cpu()`` functions (or from previous
|
||||
call to ``ticks_add()``). However, ``delta`` can be an arbitrary integer number
|
||||
or numeric expression. ``ticks_add()`` is useful for calculating deadlines for
|
||||
events/tasks. (Note: you must use ``ticks_diff()`` function to work with
|
||||
deadlines.)
|
||||
|
||||
Examples::
|
||||
|
||||
# Find out what ticks value there was 100ms ago
|
||||
print(tick_add(time.ticks_ms(), -100))
|
||||
|
||||
# Calculate deadline for operation and test for it
|
||||
deadline = tick_add(time.ticks_ms(), 200)
|
||||
while ticks_diff(deadline, time.ticks_ms()) > 0:
|
||||
do_a_little_of_something()
|
||||
|
||||
# Find out TICKS_MAX used by this port
|
||||
print(tick_add(0, -1))
|
||||
|
||||
|
||||
.. function:: ticks_diff(ticks1, ticks2)
|
||||
|
||||
Measure ticks difference between values returned from ticks_ms(), ticks_us(), or ticks_cpu()
|
||||
functions. The argument order is the same as for subtraction operator,
|
||||
``tick_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. However, values returned by
|
||||
ticks_ms(), etc. functions may wrap around, so directly using subtraction on them will
|
||||
produce incorrect result. That is why ticks_diff() is needed, it implements modular
|
||||
(or more specifically, ring) arithmetics to produce correct result even for wrap-around
|
||||
values (as long as they not too distant inbetween, see below). The function returns
|
||||
**signed** value in the range [`-TICKS_PERIOD/2` .. `TICKS_PERIOD/2-1`] (that's a typical
|
||||
range definition for two's-complement signed binary integers). If the result is negative,
|
||||
it means that `ticks1` occured earlier in time than `ticks2`. Otherwise, it means that
|
||||
`ticks1` occured after `ticks2`. This holds `only` if `ticks1` and `ticks2` are apart from
|
||||
each other for no more than `TICKS_PERIOD/2-1` ticks. If that does not hold, incorrect
|
||||
result will be returned. Specifically, if 2 tick values are apart for `TICKS_PERIOD/2-1`
|
||||
ticks, that value will be returned by the function. However, if `TICKS_PERIOD/2` of
|
||||
real-time ticks has passed between them, the function will return `-TICKS_PERIOD/2`
|
||||
instead, i.e. result value will wrap around to the negative range of possible values.
|
||||
|
||||
Informal rationale of the constraints above: Suppose you are locked in a room with no
|
||||
means to monitor passing of time except a standard 12-notch clock. Then if you look at
|
||||
dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a
|
||||
long sleep), then once you finally look again, it may seem to you that only 1 hour
|
||||
has passed. To avoid this mistake, just look at the clock regularly. Your application
|
||||
should do the same. "Too long sleep" metaphor also maps directly to application
|
||||
behavior: don't let your application run any single task for too long. Run tasks
|
||||
in steps, and do time-keeping inbetween.
|
||||
|
||||
``ticks_diff()`` is designed to accommodate various usage patterns, among them:
|
||||
|
||||
Polling with timeout. In this case, the order of events is known, and you will deal
|
||||
only with positive results of ``ticks_diff()``::
|
||||
|
||||
# Wait for GPIO pin to be asserted, but at most 500us
|
||||
start = time.ticks_us()
|
||||
while pin.value() == 0:
|
||||
if time.ticks_diff(time.ticks_us(), start) > 500:
|
||||
raise TimeoutError
|
||||
|
||||
Scheduling events. In this case, ``ticks_diff()`` result may be negative
|
||||
if an event is overdue::
|
||||
|
||||
# This code snippet is not optimized
|
||||
now = time.ticks_ms()
|
||||
scheduled_time = task.scheduled_time()
|
||||
if ticks_diff(now, scheduled_time) > 0:
|
||||
print("Too early, let's nap")
|
||||
sleep_ms(ticks_diff(now, scheduled_time))
|
||||
task.run()
|
||||
elif ticks_diff(now, scheduled_time) == 0:
|
||||
print("Right at time!")
|
||||
task.run()
|
||||
elif ticks_diff(now, scheduled_time) < 0:
|
||||
print("Oops, running late, tell task to run faster!")
|
||||
task.run(run_faster=true)
|
||||
|
||||
Note: Do not pass ``time()`` values to ``ticks_diff()``, and should use
|
||||
normal mathematical operations on them. But note that ``time()`` may (and will)
|
||||
also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem .
|
||||
|
||||
# Wait for GPIO pin to be asserted, but at most 500us
|
||||
start = time.ticks_us()
|
||||
while pin.value() == 0:
|
||||
if time.ticks_diff(start, time.ticks_us()) > 500:
|
||||
raise TimeoutError
|
||||
|
||||
.. function:: time()
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
Quick reference for the pyboard
|
||||
===============================
|
||||
|
||||
The below pinout is for PYBv1.0. You can also view pinouts for
|
||||
other versions of the pyboard:
|
||||
`PYBv1.1 <http://micropython.org/resources/pybv11-pinout.jpg>`__
|
||||
or `PYBLITEv1.0-AC <http://micropython.org/resources/pyblitev10ac-pinout.jpg>`__
|
||||
or `PYBLITEv1.0 <http://micropython.org/resources/pyblitev10-pinout.jpg>`__.
|
||||
|
||||
.. image:: http://micropython.org/resources/pybv10-pinout.jpg
|
||||
:alt: PYBv1.0 pinout
|
||||
:width: 700px
|
||||
@@ -14,14 +20,25 @@ See :mod:`pyb`. ::
|
||||
|
||||
import pyb
|
||||
|
||||
pyb.delay(50) # wait 50 milliseconds
|
||||
pyb.millis() # number of milliseconds since bootup
|
||||
pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1)
|
||||
pyb.wfi() # pause CPU, waiting for interrupt
|
||||
pyb.freq() # get CPU and bus frequencies
|
||||
pyb.freq(60000000) # set CPU freq to 60MHz
|
||||
pyb.stop() # stop CPU, waiting for external interrupt
|
||||
|
||||
Delay and timing
|
||||
----------------
|
||||
|
||||
Use the :mod:`time <utime>` module::
|
||||
|
||||
import time
|
||||
|
||||
time.sleep(1) # sleep for 1 second
|
||||
time.sleep_ms(500) # sleep for 500 milliseconds
|
||||
time.sleep_us(10) # sleep for 10 microseconds
|
||||
start = time.ticks_ms() # get value of millisecond counter
|
||||
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
|
||||
|
||||
LEDs
|
||||
----
|
||||
|
||||
|
||||
@@ -13,23 +13,23 @@ will look something like this::
|
||||
|
||||
import pyb
|
||||
#pyb.main('main.py') # main script to run after this one
|
||||
#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device
|
||||
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
|
||||
#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device
|
||||
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
|
||||
|
||||
To enable the mouse mode, uncomment the last line of the file, to
|
||||
make it look like::
|
||||
|
||||
pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
|
||||
pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
|
||||
|
||||
If you already changed your ``boot.py`` file, then the minimum code it
|
||||
needs to work is::
|
||||
|
||||
import pyb
|
||||
pyb.usb_mode('CDC+HID')
|
||||
pyb.usb_mode('VCP+HID')
|
||||
|
||||
This tells the pyboard to configure itself as a CDC (serial) and HID
|
||||
(human interface device, in our case a mouse) USB device when it boots
|
||||
up.
|
||||
This tells the pyboard to configure itself as a VCP (Virtual COM Port,
|
||||
ie serial port) and HID (human interface device, in our case a mouse)
|
||||
USB device when it boots up.
|
||||
|
||||
Eject/unmount the pyboard drive and reset it using the RST switch.
|
||||
Your PC should now detect the pyboard as a mouse!
|
||||
@@ -41,7 +41,8 @@ To get the py-mouse to do anything we need to send mouse events to the PC.
|
||||
We will first do this manually using the REPL prompt. Connect to your
|
||||
pyboard using your serial program and type the following::
|
||||
|
||||
>>> pyb.hid((0, 10, 0, 0))
|
||||
>>> hid = pyb.USB_HID()
|
||||
>>> hid.send((0, 10, 0, 0))
|
||||
|
||||
Your mouse should move 10 pixels to the right! In the command above you
|
||||
are sending 4 pieces of information: button status, x, y and scroll. The
|
||||
@@ -52,7 +53,7 @@ Let's make the mouse oscillate left and right::
|
||||
>>> import math
|
||||
>>> def osc(n, d):
|
||||
... for i in range(n):
|
||||
... pyb.hid((0, int(20 * math.sin(i / 10)), 0, 0))
|
||||
... hid.send((0, int(20 * math.sin(i / 10)), 0, 0))
|
||||
... pyb.delay(d)
|
||||
...
|
||||
>>> osc(100, 50)
|
||||
@@ -100,9 +101,10 @@ In ``main.py`` put the following code::
|
||||
|
||||
switch = pyb.Switch()
|
||||
accel = pyb.Accel()
|
||||
hid = pyb.USB_HID()
|
||||
|
||||
while not switch():
|
||||
pyb.hid((0, accel.x(), accel.y(), 0))
|
||||
hid.send((0, accel.x(), accel.y(), 0))
|
||||
pyb.delay(20)
|
||||
|
||||
Save your file, eject/unmount your pyboard drive, and reset it using the RST
|
||||
@@ -112,7 +114,7 @@ the mouse around. Try it out, and see if you can make the mouse stand still!
|
||||
Press the USR switch to stop the mouse motion.
|
||||
|
||||
You'll note that the y-axis is inverted. That's easy to fix: just put a
|
||||
minus sign in front of the y-coordinate in the ``pyb.hid()`` line above.
|
||||
minus sign in front of the y-coordinate in the ``hid.send()`` line above.
|
||||
|
||||
Restoring your pyboard to normal
|
||||
--------------------------------
|
||||
@@ -121,9 +123,9 @@ If you leave your pyboard as-is, it'll behave as a mouse everytime you plug
|
||||
it in. You probably want to change it back to normal. To do this you need
|
||||
to first enter safe mode (see above), and then edit the ``boot.py`` file.
|
||||
In the ``boot.py`` file, comment out (put a # in front of) the line with the
|
||||
``CDC+HID`` setting, so it looks like::
|
||||
``VCP+HID`` setting, so it looks like::
|
||||
|
||||
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
|
||||
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
|
||||
|
||||
Save your file, eject/unmount the drive, and reset the pyboard. It is now
|
||||
back to normal operating mode.
|
||||
|
||||
456
docs/reference/constrained.rst
Normal file
456
docs/reference/constrained.rst
Normal file
@@ -0,0 +1,456 @@
|
||||
.. _constrained:
|
||||
|
||||
MicroPython on Microcontrollers
|
||||
===============================
|
||||
|
||||
MicroPython is designed to be capable of running on microcontrollers. These
|
||||
have hardware limitations which may be unfamiliar to programmers more familiar
|
||||
with conventional computers. In particular the amount of RAM and nonvolatile
|
||||
"disk" (flash memory) storage is limited. This tutorial offers ways to make
|
||||
the most of the limited resources. Because MicroPython runs on controllers
|
||||
based on a variety of architectures, the methods presented are generic: in some
|
||||
cases it will be necessary to obtain detailed information from platform specific
|
||||
documentation.
|
||||
|
||||
Flash Memory
|
||||
------------
|
||||
|
||||
On the Pyboard the simple way to address the limited capacity is to fit a micro
|
||||
SD card. In some cases this is impractical, either because the device does not
|
||||
have an SD card slot or for reasons of cost or power consumption; hence the
|
||||
on-chip flash must be used. The firmware including the MicroPython subsystem is
|
||||
stored in the onboard flash. The remaining capacity is available for use. For
|
||||
reasons connected with the physical architecture of the flash memory part of
|
||||
this capacity may be inaccessible as a filesystem. In such cases this space may
|
||||
be employed by incorporating user modules into a firmware build which is then
|
||||
flashed to the device.
|
||||
|
||||
There are two ways to achieve this: frozen modules and frozen bytecode. Frozen
|
||||
modules store the Python source with the firmware. Frozen bytecode uses the
|
||||
cross compiler to convert the source to bytecode which is then stored with the
|
||||
firmware. In either case the module may be accessed with an import statement:
|
||||
|
||||
.. code::
|
||||
|
||||
import mymodule
|
||||
|
||||
The procedure for producing frozen modules and bytecode is platform dependent;
|
||||
instructions for building the firmware can be found in the README files in the
|
||||
relevant part of the source tree.
|
||||
|
||||
In general terms the steps are as follows:
|
||||
|
||||
* Clone the MicroPython `repository <https://github.com/micropython/micropython>`_.
|
||||
* Acquire the (platform specific) toolchain to build the firmware.
|
||||
* Build the cross compiler.
|
||||
* Place the modules to be frozen in a specified directory (dependent on whether
|
||||
the module is to be frozen as source or as bytecode).
|
||||
* Build the firmware. A specific command may be required to build frozen
|
||||
code of either type - see the platform documentation.
|
||||
* Flash the firmware to the device.
|
||||
|
||||
RAM
|
||||
---
|
||||
|
||||
When reducing RAM usage there are two phases to consider: compilation and
|
||||
execution. In addition to memory consumption, there is also an issue known as
|
||||
heap fragmentation. In general terms it is best to minimise the repeated
|
||||
creation and destruction of objects. The reason for this is covered in the
|
||||
section covering the `heap`_.
|
||||
|
||||
Compilation Phase
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
When a module is imported, MicroPython compiles the code to bytecode which is
|
||||
then executed by the MicroPython virtual machine (VM). The bytecode is stored
|
||||
in RAM. The compiler itself requires RAM, but this becomes available for use
|
||||
when the compilation has completed.
|
||||
|
||||
If a number of modules have already been imported the situation can arise where
|
||||
there is insufficient RAM to run the compiler. In this case the import
|
||||
statement will produce a memory exception.
|
||||
|
||||
If a module instantiates global objects on import it will consume RAM at the
|
||||
time of import, which is then unavailable for the compiler to use on subsequent
|
||||
imports. In general it is best to avoid code which runs on import; a better
|
||||
approach is to have initialisation code which is run by the application after
|
||||
all modules have been imported. This maximises the RAM available to the
|
||||
compiler.
|
||||
|
||||
If RAM is still insufficient to compile all modules one solution is to
|
||||
precompile modules. MicroPython has a cross compiler capable of compiling Python
|
||||
modules to bytecode (see the README in the mpy-cross directory). The resulting
|
||||
bytecode file has a .mpy extension; it may be copied to the filesystem and
|
||||
imported in the usual way. Alternatively some or all modules may be implemented
|
||||
as frozen bytecode: on most platforms this saves even more RAM as the bytecode
|
||||
is run directly from flash rather than being stored in RAM.
|
||||
|
||||
Execution Phase
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
There are a number of coding techniques for reducing RAM usage.
|
||||
|
||||
**Constants**
|
||||
|
||||
MicroPython provides a ``const`` keyword which may be used as follows:
|
||||
|
||||
.. code::
|
||||
|
||||
from micropython import const
|
||||
ROWS = const(33)
|
||||
_COLS = const(0x10)
|
||||
a = ROWS
|
||||
b = _COLS
|
||||
|
||||
In both instances where the constant is assigned to a variable the compiler
|
||||
will avoid coding a lookup to the name of the constant by substituting its
|
||||
literal value. This saves bytecode and hence RAM. However the ``ROWS`` value
|
||||
will occupy at least two machine words, one each for the key and value in the
|
||||
globals dictionary. The presence in the dictionary is necessary because another
|
||||
module might import or use it. This RAM can be saved by prepending the name
|
||||
with an underscore as in ``_COLS``: this symbol is not visible outside the
|
||||
module so will not occupy RAM.
|
||||
|
||||
The argument to ``const()`` may be anything which, at compile time, evaluates
|
||||
to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const
|
||||
symbols that have already been defined, e.g. ``1 << BIT``.
|
||||
|
||||
**Constant data structures**
|
||||
|
||||
Where there is a substantial volume of constant data and the platform supports
|
||||
execution from Flash, RAM may be saved as follows. The data should be located in
|
||||
Python modules and frozen as bytecode. The data must be defined as ``bytes``
|
||||
objects. The compiler 'knows' that ``bytes`` objects are immutable and ensures
|
||||
that the objects remain in flash memory rather than being copied to RAM. The
|
||||
``ustruct`` module can assist in converting between ``bytes`` types and other
|
||||
Python built-in types.
|
||||
|
||||
When considering the implications of frozen bytecode, note that in Python
|
||||
strings, floats, bytes, integers and complex numbers are immutable. Accordingly
|
||||
these will be frozen into flash. Thus, in the line
|
||||
|
||||
.. code::
|
||||
|
||||
mystring = "The quick brown fox"
|
||||
|
||||
the actual string "The quick brown fox" will reside in flash. At runtime a
|
||||
reference to the string is assigned to the *variable* ``mystring``. The reference
|
||||
occupies a single machine word. In principle a long integer could be used to
|
||||
store constant data:
|
||||
|
||||
.. code::
|
||||
|
||||
bar = 0xDEADBEEF0000DEADBEEF
|
||||
|
||||
As in the string example, at runtime a reference to the arbitrarily large
|
||||
integer is assigned to the variable ``bar``. That reference occupies a
|
||||
single machine word.
|
||||
|
||||
It might be expected that tuples of integers could be employed for the purpose
|
||||
of storing constant data with minimal RAM use. With the current compiler this
|
||||
is ineffective (the code works, but RAM is not saved).
|
||||
|
||||
.. code::
|
||||
|
||||
foo = (1, 2, 3, 4, 5, 6, 100000)
|
||||
|
||||
At runtime the tuple will be located in RAM. This may be subject to future
|
||||
improvement.
|
||||
|
||||
**Needless object creation**
|
||||
|
||||
There are a number of situations where objects may unwittingly be created and
|
||||
destroyed. This can reduce the usability of RAM through fragmentation. The
|
||||
following sections discuss instances of this.
|
||||
|
||||
**String concatenation**
|
||||
|
||||
Consider the following code fragments which aim to produce constant strings:
|
||||
|
||||
.. code::
|
||||
|
||||
var = "foo" + "bar"
|
||||
var1 = "foo" "bar"
|
||||
var2 = """\
|
||||
foo\
|
||||
bar"""
|
||||
|
||||
Each produces the same outcome, however the first needlessly creates two string
|
||||
objects at runtime, allocates more RAM for concatenation before producing the
|
||||
third. The others perform the concatenation at compile time which is more
|
||||
efficient, reducing fragmentation.
|
||||
|
||||
Where strings must be dynamically created before being fed to a stream such as
|
||||
a file it will save RAM if this is done in a piecemeal fashion. Rather than
|
||||
creating a large string object, create a substring and feed it to the stream
|
||||
before dealing with the next.
|
||||
|
||||
The best way to create dynamic strings is by means of the string ``format``
|
||||
method:
|
||||
|
||||
.. code::
|
||||
|
||||
var = "Temperature {:5.2f} Pressure {:06d}\n".format(temp, press)
|
||||
|
||||
**Buffers**
|
||||
|
||||
When accessing devices such as instances of UART, I2C and SPI interfaces, using
|
||||
pre-allocated buffers avoids the creation of needless objects. Consider these
|
||||
two loops:
|
||||
|
||||
.. code::
|
||||
|
||||
while True:
|
||||
var = spi.read(100)
|
||||
# process data
|
||||
|
||||
buf = bytearray(100)
|
||||
while True:
|
||||
spi.readinto(buf)
|
||||
# process data in buf
|
||||
|
||||
The first creates a buffer on each pass whereas the second re-uses a pre-allocated
|
||||
buffer; this is both faster and more efficient in terms of memory fragmentation.
|
||||
|
||||
**Bytes are smaller than ints**
|
||||
|
||||
On most platforms an integer consumes four bytes. Consider the two calls to the
|
||||
function ``foo()``:
|
||||
|
||||
.. code::
|
||||
|
||||
def foo(bar):
|
||||
for x in bar:
|
||||
print(x)
|
||||
foo((1, 2, 0xff))
|
||||
foo(b'\1\2\xff')
|
||||
|
||||
In the first call a tuple of integers is created in RAM. The second efficiently
|
||||
creates a ``bytes`` object consuming the minimum amount of RAM. If the module
|
||||
were frozen as bytecode, the ``bytes`` object would reside in flash.
|
||||
|
||||
**Strings Versus Bytes**
|
||||
|
||||
Python3 introduced Unicode support. This introduced a distinction between a
|
||||
string and an array of bytes. MicroPython ensures that Unicode strings take no
|
||||
additional space so long as all characters in the string are ASCII (i.e. have
|
||||
a value < 126). If values in the full 8-bit range are required ``bytes`` and
|
||||
``bytearray`` objects can be used to ensure that no additional space will be
|
||||
required. Note that most string methods (e.g. ``strip()``) apply also to ``bytes``
|
||||
instances so the process of eliminating Unicode can be painless.
|
||||
|
||||
.. code::
|
||||
|
||||
s = 'the quick brown fox' # A string instance
|
||||
b = b'the quick brown fox' # a bytes instance
|
||||
|
||||
Where it is necessary to convert between strings and bytes the string ``encode``
|
||||
and the bytes ``decode`` methods can be used. Note that both strings and bytes
|
||||
are immutable. Any operation which takes as input such an object and produces
|
||||
another implies at least one RAM allocation to produce the result. In the
|
||||
second line below a new bytes object is allocated. This would also occur if ``foo``
|
||||
were a string.
|
||||
|
||||
.. code::
|
||||
|
||||
foo = b' empty whitespace'
|
||||
foo = foo.lstrip()
|
||||
|
||||
**Runtime compiler execution**
|
||||
|
||||
The Python keywords ``eval`` and ``exec`` invoke the compiler at runtime, which
|
||||
requires significant amounts of RAM. Note that the ``pickle`` library employs
|
||||
``exec``. It may be more RAM efficient to use the ``json`` library for object
|
||||
serialisation.
|
||||
|
||||
**Storing strings in flash**
|
||||
|
||||
Python strings are immutable hence have the potential to be stored in read only
|
||||
memory. The compiler can place in flash strings defined in Python code. As with
|
||||
frozen modules it is necessary to have a copy of the source tree on the PC and
|
||||
the toolchain to build the firmware. The procedure will work even if the
|
||||
modules have not been fully debugged, so long as they can be imported and run.
|
||||
|
||||
After importing the modules, execute:
|
||||
|
||||
.. code::
|
||||
|
||||
micropython.qstr_info(1)
|
||||
|
||||
Then copy and paste all the Q(xxx) lines into a text editor. Check for and
|
||||
remove lines which are obviously invalid. Open the file qstrdefsport.h which
|
||||
will be found in stmhal (or the equivalent directory for the architecture in
|
||||
use). Copy and paste the corrected lines at the end of the file. Save the file,
|
||||
rebuild and flash the firmware. The outcome can be checked by importing the
|
||||
modules and again issuing:
|
||||
|
||||
.. code::
|
||||
|
||||
micropython.qstr_info(1)
|
||||
|
||||
The Q(xxx) lines should be gone.
|
||||
|
||||
.. _heap:
|
||||
|
||||
The Heap
|
||||
--------
|
||||
|
||||
When a running program instantiates an object the necessary RAM is allocated
|
||||
from a fixed size pool known as the heap. When the object goes out of scope (in
|
||||
other words becomes inaccessible to code) the redundant object is known as
|
||||
"garbage". A process known as "garbage collection" (GC) reclaims that memory,
|
||||
returning it to the free heap. This process runs automatically, however it can
|
||||
be invoked directly by issuing ``gc.collect()``.
|
||||
|
||||
The discourse on this is somewhat involved. For a 'quick fix' issue the
|
||||
following periodically:
|
||||
|
||||
.. code::
|
||||
|
||||
gc.collect()
|
||||
gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
|
||||
|
||||
Fragmentation
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Say a program creates an object ``foo``, then an object ``bar``. Subsequently
|
||||
``foo`` goes out of scope but ``bar`` remains. The RAM used by ``foo`` will be
|
||||
reclaimed by GC. However if ``bar`` was allocated to a higher address, the
|
||||
RAM reclaimed from ``foo`` will only be of use for objects no bigger than
|
||||
``foo``. In a complex or long running program the heap can become fragmented:
|
||||
despite there being a substantial amount of RAM available, there is insufficient
|
||||
contiguous space to allocate a particular object, and the program fails with a
|
||||
memory error.
|
||||
|
||||
The techniques outlined above aim to minimise this. Where large permanent buffers
|
||||
or other objects are required it is best to instantiate these early in the
|
||||
process of program execution before fragmentation can occur. Further improvements
|
||||
may be made by monitoring the state of the heap and by controlling GC; these are
|
||||
outlined below.
|
||||
|
||||
Reporting
|
||||
~~~~~~~~~
|
||||
|
||||
A number of library functions are available to report on memory allocation and
|
||||
to control GC. These are to be found in the ``gc`` and ``micropython`` modules.
|
||||
The following example may be pasted at the REPL (``ctrl e`` to enter paste mode,
|
||||
``ctrl d`` to run it).
|
||||
|
||||
.. code::
|
||||
|
||||
import gc
|
||||
import micropython
|
||||
gc.collect()
|
||||
micropython.mem_info()
|
||||
print('-----------------------------')
|
||||
print('Initial free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
|
||||
def func():
|
||||
a = bytearray(10000)
|
||||
gc.collect()
|
||||
print('Func definition: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
|
||||
func()
|
||||
print('Func run free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
|
||||
gc.collect()
|
||||
print('Garbage collect free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
|
||||
print('-----------------------------')
|
||||
micropython.mem_info(1)
|
||||
|
||||
Methods employed above:
|
||||
|
||||
* ``gc.collect()`` Force a garbage collection. See footnote.
|
||||
* ``micropython.mem_info()`` Print a summary of RAM utilisation.
|
||||
* ``gc.mem_free()`` Return the free heap size in bytes.
|
||||
* ``gc.mem_alloc()`` Return the number of bytes currently allocated.
|
||||
* ``micropython.mem_info(1)`` Print a table of heap utilisation (detailed below).
|
||||
|
||||
The numbers produced are dependent on the platform, but it can be seen that
|
||||
declaring the function uses a small amount of RAM in the form of bytecode
|
||||
emitted by the compiler (the RAM used by the compiler has been reclaimed).
|
||||
Running the function uses over 10KiB, but on return ``a`` is garbage because it
|
||||
is out of scope and cannot be referenced. The final ``gc.collect()`` recovers
|
||||
that memory.
|
||||
|
||||
The final output produced by ``micropython.mem_info(1)`` will vary in detail but
|
||||
may be interpreted as follows:
|
||||
|
||||
====== =================
|
||||
Symbol Meaning
|
||||
====== =================
|
||||
. free block
|
||||
h head block
|
||||
= tail block
|
||||
m marked head block
|
||||
T tuple
|
||||
L list
|
||||
D dict
|
||||
F float
|
||||
B byte code
|
||||
M module
|
||||
====== =================
|
||||
|
||||
Each letter represents a single block of memory, a block being 16 bytes. So each
|
||||
line of the heap dump represents 0x400 bytes or 1KiB of RAM.
|
||||
|
||||
Control of Garbage Collection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A GC can be demanded at any time by issuing ``gc.collect()``. It is advantageous
|
||||
to do this at intervals, firstly to pre-empt fragmentation and secondly for
|
||||
performance. A GC can take several milliseconds but is quicker when there is
|
||||
little work to do (about 1ms on the Pyboard). An explicit call can minimise that
|
||||
delay while ensuring it occurs at points in the program when it is acceptable.
|
||||
|
||||
Automatic GC is provoked under the following circumstances. When an attempt at
|
||||
allocation fails, a GC is performed and the allocation re-tried. Only if this
|
||||
fails is an exception raised. Secondly an automatic GC will be triggered if the
|
||||
amount of free RAM falls below a threshold. This threshold can be adapted as
|
||||
execution progresses:
|
||||
|
||||
.. code::
|
||||
|
||||
gc.collect()
|
||||
gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
|
||||
|
||||
This will provoke a GC when more than 25% of the currently free heap becomes
|
||||
occupied.
|
||||
|
||||
In general modules should instantiate data objects at runtime using constructors
|
||||
or other initialisation functions. The reason is that if this occurs on
|
||||
initialisation the compiler may be starved of RAM when subsequent modules are
|
||||
imported. If modules do instantiate data on import then ``gc.collect()`` issued
|
||||
after the import will ameliorate the problem.
|
||||
|
||||
String Operations
|
||||
-----------------
|
||||
|
||||
MicroPython handles strings in an efficient manner and understanding this can
|
||||
help in designing applications to run on microcontrollers. When a module
|
||||
is compiled, strings which occur multiple times are stored once only, a process
|
||||
known as string interning. In MicroPython an interned string is known as a ``qstr``.
|
||||
In a module imported normally that single instance will be located in RAM, but
|
||||
as described above, in modules frozen as bytecode it will be located in flash.
|
||||
|
||||
String comparisons are also performed efficiently using hashing rather than
|
||||
character by character. The penalty for using strings rather than integers may
|
||||
hence be small both in terms of performance and RAM usage - a fact which may
|
||||
come as a surprise to C programmers.
|
||||
|
||||
Postscript
|
||||
----------
|
||||
|
||||
MicroPython passes, returns and (by default) copies objects by reference. A
|
||||
reference occupies a single machine word so these processes are efficient in
|
||||
RAM usage and speed.
|
||||
|
||||
Where variables are required whose size is neither a byte nor a machine word
|
||||
there are standard libraries which can assist in storing these efficiently and
|
||||
in performing conversions. See the ``array``, ``ustruct`` and ``uctypes``
|
||||
modules.
|
||||
|
||||
Footnote: gc.collect() return value
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
On Unix and Windows platforms the ``gc.collect()`` method returns an integer
|
||||
which signifies the number of distinct memory regions that were reclaimed in the
|
||||
collection (more precisely, the number of heads that were turned into frees). For
|
||||
efficiency reasons bare metal ports do not return this value.
|
||||
@@ -15,6 +15,7 @@ MicroPython are described in the sections here.
|
||||
repl.rst
|
||||
isr_rules.rst
|
||||
speed_python.rst
|
||||
constrained.rst
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
|
||||
@@ -110,6 +110,19 @@ the flag. The memory allocation occurs in the main program code when the object
|
||||
The MicroPython library I/O methods usually provide an option to use a pre-allocated buffer. For
|
||||
example ``pyb.i2c.recv()`` can accept a mutable buffer as its first argument: this enables its use in an ISR.
|
||||
|
||||
A means of creating an object without employing a class or globals is as follows:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def set_volume(t, buf=bytearray(3)):
|
||||
buf[0] = 0xa5
|
||||
buf[1] = t >> 4
|
||||
buf[2] = 0x5a
|
||||
return buf
|
||||
|
||||
The compiler instantiates the default ``buf`` argument when the function is
|
||||
loaded for the first time (usually when the module it's in is imported).
|
||||
|
||||
Use of Python objects
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -300,3 +313,20 @@ that access to the critical variables is denied. A simple example of a mutex may
|
||||
but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are
|
||||
virtually unaffected.
|
||||
|
||||
Interrupts and the REPL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Interrupt handlers, such as those associated with timers, can continue to run
|
||||
after a program terminates. This may produce unexpected results where you might
|
||||
have expected the object raising the callback to have gone out of scope. For
|
||||
example on the Pyboard:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def bar():
|
||||
foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end=''))
|
||||
|
||||
bar()
|
||||
|
||||
This continues to run until the timer is explicitly disabled or the board is
|
||||
reset with ``ctrl D``.
|
||||
|
||||
@@ -132,7 +132,7 @@ The following enables any function or method to be timed by adding an
|
||||
def new_func(*args, **kwargs):
|
||||
t = time.ticks_us()
|
||||
result = f(*args, **kwargs)
|
||||
delta = time.ticks_diff(t, time.ticks_us())
|
||||
delta = time.ticks_diff(time.ticks_us(), t)
|
||||
print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000))
|
||||
return result
|
||||
return new_func
|
||||
|
||||
@@ -14,18 +14,18 @@ all divisions must be performed using '//' instead of '/'. Example::
|
||||
Before applying power
|
||||
---------------------
|
||||
|
||||
.. warning::
|
||||
.. warning::
|
||||
|
||||
The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higher
|
||||
than 3.6V will cause irreparable damage to the board. ADC pins, when configured
|
||||
than 3.6V will cause irreparable damage to the board. ADC pins, when configured
|
||||
in analog mode cannot withstand voltages above 1.8V. Keep these considerations in
|
||||
mind when wiring your electronics.
|
||||
|
||||
WLAN default behaviour
|
||||
----------------------
|
||||
|
||||
When the WiPy boots with the default factory configuration starts in Access Point
|
||||
mode with ``ssid`` that starts with: ``wipy-wlan`` and ``key: www.wipy.io``.
|
||||
When the WiPy boots with the default factory configuration starts in Access Point
|
||||
mode with ``ssid`` that starts with: ``wipy-wlan`` and ``key: www.wipy.io``.
|
||||
Connect to this network and the WiPy will be reachable at ``192.168.1.1``. In order
|
||||
to gain access to the interactive prompt, open a telnet session to that IP address on
|
||||
the default port (23). You will be asked for credentials:
|
||||
@@ -98,7 +98,7 @@ the WiPy by pressing the switch on the board, or by typing::
|
||||
>>> import machine
|
||||
>>> machine.reset()
|
||||
|
||||
Software updates can be found in: https://github.com/wipy/wipy/releases (**Binaries.zip**).
|
||||
Software updates can be found in: https://github.com/wipy/wipy/releases (**Binaries.zip**).
|
||||
It's always recommended to update to the latest software, but make sure to
|
||||
read the **release notes** before.
|
||||
|
||||
@@ -122,7 +122,7 @@ Boot modes and safe boot
|
||||
------------------------
|
||||
|
||||
If you power up normally, or press the reset button, the WiPy will boot
|
||||
into standard mode; the ``boot.py`` file will be executed first, then
|
||||
into standard mode; the ``boot.py`` file will be executed first, then
|
||||
``main.py`` will run.
|
||||
|
||||
You can override this boot sequence by pulling ``GP28`` **up** (connect
|
||||
@@ -178,4 +178,4 @@ Details on sleep modes
|
||||
configuration required.
|
||||
* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC``
|
||||
and ``WLAN``
|
||||
* ``machine.deepsleep()``: ~5uA. Wake sources are ``Pin`` and ``RTC``.
|
||||
* ``machine.deepsleep()``: ~350uA. Wake sources are ``Pin`` and ``RTC``.
|
||||
|
||||
@@ -51,11 +51,10 @@ See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`. :
|
||||
|
||||
tim = Timer(0, mode=Timer.PERIODIC)
|
||||
tim_a = tim.channel(Timer.A, freq=1000)
|
||||
tim_a.time() # get the value in microseconds
|
||||
tim_a.freq(5) # 5 Hz
|
||||
|
||||
p_out = Pin('GP2', mode=Pin.OUT)
|
||||
tim_a.irq(handler=lambda t: p_out.toggle())
|
||||
tim_a.irq(trigger=Timer.TIMEOUT, handler=lambda t: p_out.toggle())
|
||||
|
||||
PWM (pulse width modulation)
|
||||
----------------------------
|
||||
@@ -135,10 +134,9 @@ Real time clock (RTC)
|
||||
|
||||
See :ref:`machine.RTC <machine.RTC>` ::
|
||||
|
||||
import machine
|
||||
from machine import RTC
|
||||
|
||||
rtc = machine.RTC() # init with default time and date
|
||||
rtc = RTC() # init with default time and date
|
||||
rtc = RTC(datetime=(2015, 8, 29, 9, 0, 0, 0, None)) # init with a specific time and date
|
||||
print(rtc.now())
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ STATIC tSpiInformation sSpiInformation;
|
||||
STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE];
|
||||
unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE];
|
||||
|
||||
STATIC const mp_obj_fun_builtin_t irq_callback_obj;
|
||||
STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj;
|
||||
|
||||
// set the pins to use to communicate with the CC3000
|
||||
// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef*
|
||||
|
||||
@@ -84,6 +84,6 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
|
||||
|
||||
timeout:
|
||||
mp_hal_quiet_timing_exit(irq_state);
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
|
||||
mp_raise_OSError(MP_ETIMEDOUT);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto);
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#include "py/obj.h"
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(dht_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(dht_readinto_obj);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
|
||||
|
||||
from micropython import const
|
||||
import time
|
||||
import framebuf
|
||||
|
||||
@@ -31,7 +32,7 @@ class SSD1306:
|
||||
self.external_vcc = external_vcc
|
||||
self.pages = self.height // 8
|
||||
self.buffer = bytearray(self.pages * self.width)
|
||||
self.framebuf = framebuf.FrameBuffer1(self.buffer, self.width, self.height)
|
||||
self.framebuf = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MVLSB)
|
||||
self.poweron()
|
||||
self.init_display()
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""NRF24L01 driver for Micro Python
|
||||
"""
|
||||
|
||||
from micropython import const
|
||||
import pyb
|
||||
|
||||
# nRF24L01+ registers
|
||||
|
||||
@@ -93,6 +93,9 @@ class DS18X20(object):
|
||||
temp = temp_read - 0.25 + (count_per_c - count_remain) / count_per_c
|
||||
return temp
|
||||
elif rom0 == 0x28:
|
||||
return (temp_msb << 8 | temp_lsb) / 16
|
||||
temp = (temp_msb << 8 | temp_lsb) / 16
|
||||
if (temp_msb & 0xf8) == 0xf8: # for negative temperature
|
||||
temp -= 0x1000
|
||||
return temp
|
||||
else:
|
||||
assert False
|
||||
|
||||
@@ -60,7 +60,7 @@ class OneWire:
|
||||
|
||||
# cache a bunch of methods and attributes. This is necessary in _write_bit and
|
||||
# _read_bit to achieve the timing required by the OneWire protocol.
|
||||
self.cache = (pin.init, pin.value, pin.OUT_PP, pin.IN, pin.PULL_NONE)
|
||||
self.cache = (pin.init, pin.value, pin.OUT_PP, pin.IN, pin.PULL_UP)
|
||||
|
||||
pin.init(pin.IN, pin.PULL_UP)
|
||||
|
||||
|
||||
@@ -4,31 +4,42 @@ Micro Python driver for SD cards using SPI bus.
|
||||
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
|
||||
methods so the device can be mounted as a filesystem.
|
||||
|
||||
Example usage:
|
||||
Example usage on pyboard:
|
||||
|
||||
import pyb, sdcard, os
|
||||
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
|
||||
pyb.mount(sd, '/sd2')
|
||||
os.listdir('/')
|
||||
|
||||
Example usage on ESP8266:
|
||||
|
||||
import machine, sdcard, os
|
||||
sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15))
|
||||
os.umount()
|
||||
os.VfsFat(sd, "")
|
||||
os.listdir()
|
||||
|
||||
"""
|
||||
|
||||
import pyb
|
||||
from micropython import const
|
||||
import time
|
||||
|
||||
|
||||
_CMD_TIMEOUT = const(100)
|
||||
|
||||
_R1_IDLE_STATE = const(1 << 0)
|
||||
#R1_ERASE_RESET = const(1 << 1)
|
||||
_R1_ILLEGAL_COMMAND = const(1 << 2)
|
||||
#R1_COM_CRC_ERROR = const(1 << 3)
|
||||
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
|
||||
#R1_ADDRESS_ERROR = const(1 << 5)
|
||||
#R1_PARAMETER_ERROR = const(1 << 6)
|
||||
_TOKEN_CMD25 = const(0xfc)
|
||||
_TOKEN_STOP_TRAN = const(0xfd)
|
||||
_TOKEN_DATA = const(0xfe)
|
||||
|
||||
|
||||
class SDCard:
|
||||
CMD_TIMEOUT = const(100)
|
||||
|
||||
R1_IDLE_STATE = const(1 << 0)
|
||||
#R1_ERASE_RESET = const(1 << 1)
|
||||
R1_ILLEGAL_COMMAND = const(1 << 2)
|
||||
#R1_COM_CRC_ERROR = const(1 << 3)
|
||||
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
|
||||
#R1_ADDRESS_ERROR = const(1 << 5)
|
||||
#R1_PARAMETER_ERROR = const(1 << 6)
|
||||
TOKEN_CMD25 = const(0xfc)
|
||||
TOKEN_STOP_TRAN = const(0xfd)
|
||||
TOKEN_DATA = const(0xfe)
|
||||
|
||||
def __init__(self, spi, cs):
|
||||
self.spi = spi
|
||||
self.cs = cs
|
||||
@@ -42,30 +53,39 @@ class SDCard:
|
||||
# initialise the card
|
||||
self.init_card()
|
||||
|
||||
def init_spi(self, baudrate):
|
||||
try:
|
||||
master = self.spi.MASTER
|
||||
except AttributeError:
|
||||
# on ESP8266
|
||||
self.spi.init(baudrate=baudrate, phase=0, polarity=0)
|
||||
else:
|
||||
# on pyboard
|
||||
self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
|
||||
|
||||
def init_card(self):
|
||||
# init CS pin
|
||||
self.cs.high()
|
||||
self.cs.init(self.cs.OUT_PP)
|
||||
self.cs.init(self.cs.OUT, value=1)
|
||||
|
||||
# init SPI bus; use low data rate for initialisation
|
||||
self.spi.init(self.spi.MASTER, baudrate=100000, phase=0, polarity=0)
|
||||
self.init_spi(100000)
|
||||
|
||||
# clock card at least 100 cycles with cs high
|
||||
for i in range(16):
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
# CMD0: init card; should return R1_IDLE_STATE (allow 5 attempts)
|
||||
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
|
||||
for _ in range(5):
|
||||
if self.cmd(0, 0, 0x95) == R1_IDLE_STATE:
|
||||
if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
|
||||
break
|
||||
else:
|
||||
raise OSError("no SD card")
|
||||
|
||||
# CMD8: determine card version
|
||||
r = self.cmd(8, 0x01aa, 0x87, 4)
|
||||
if r == R1_IDLE_STATE:
|
||||
if r == _R1_IDLE_STATE:
|
||||
self.init_card_v2()
|
||||
elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND):
|
||||
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
|
||||
self.init_card_v1()
|
||||
else:
|
||||
raise OSError("couldn't determine SD card version")
|
||||
@@ -86,10 +106,10 @@ class SDCard:
|
||||
raise OSError("can't set 512 block size")
|
||||
|
||||
# set to high data rate now that it's initialised
|
||||
self.spi.init(self.spi.MASTER, baudrate=1320000, phase=0, polarity=0)
|
||||
self.init_spi(1320000)
|
||||
|
||||
def init_card_v1(self):
|
||||
for i in range(CMD_TIMEOUT):
|
||||
for i in range(_CMD_TIMEOUT):
|
||||
self.cmd(55, 0, 0)
|
||||
if self.cmd(41, 0, 0) == 0:
|
||||
self.cdv = 512
|
||||
@@ -98,8 +118,8 @@ class SDCard:
|
||||
raise OSError("timeout waiting for v1 card")
|
||||
|
||||
def init_card_v2(self):
|
||||
for i in range(CMD_TIMEOUT):
|
||||
pyb.delay(50)
|
||||
for i in range(_CMD_TIMEOUT):
|
||||
time.sleep_ms(50)
|
||||
self.cmd(58, 0, 0, 4)
|
||||
self.cmd(55, 0, 0)
|
||||
if self.cmd(41, 0x40000000, 0) == 0:
|
||||
@@ -120,87 +140,87 @@ class SDCard:
|
||||
buf[3] = arg >> 8
|
||||
buf[4] = arg
|
||||
buf[5] = crc
|
||||
self.spi.send(buf)
|
||||
self.spi.write(buf)
|
||||
|
||||
# wait for the repsonse (response[7] == 0)
|
||||
for i in range(CMD_TIMEOUT):
|
||||
response = self.spi.send_recv(0xff)[0]
|
||||
for i in range(_CMD_TIMEOUT):
|
||||
response = self.spi.read(1, 0xff)[0]
|
||||
if not (response & 0x80):
|
||||
# this could be a big-endian integer that we are getting here
|
||||
for j in range(final):
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
if release:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return response
|
||||
|
||||
# timeout
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return -1
|
||||
|
||||
def cmd_nodata(self, cmd):
|
||||
self.spi.send(cmd)
|
||||
self.spi.send_recv(0xff) # ignore stuff byte
|
||||
for _ in range(CMD_TIMEOUT):
|
||||
if self.spi.send_recv(0xff)[0] == 0xff:
|
||||
self.spi.write(cmd)
|
||||
self.spi.read(1, 0xff) # ignore stuff byte
|
||||
for _ in range(_CMD_TIMEOUT):
|
||||
if self.spi.read(1, 0xff)[0] == 0xff:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return 0 # OK
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return 1 # timeout
|
||||
|
||||
def readinto(self, buf):
|
||||
self.cs.low()
|
||||
|
||||
# read until start byte (0xff)
|
||||
while self.spi.send_recv(0xff)[0] != 0xfe:
|
||||
while self.spi.read(1, 0xff)[0] != 0xfe:
|
||||
pass
|
||||
|
||||
# read data
|
||||
mv = self.dummybuf_memoryview[:len(buf)]
|
||||
self.spi.send_recv(mv, recv=buf)
|
||||
self.spi.write_readinto(mv, buf)
|
||||
|
||||
# read checksum
|
||||
self.spi.send(0xff)
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
def write(self, token, buf):
|
||||
self.cs.low()
|
||||
|
||||
# send: start of block, data, checksum
|
||||
self.spi.send(token)
|
||||
self.spi.send(buf)
|
||||
self.spi.send(0xff)
|
||||
self.spi.send(0xff)
|
||||
self.spi.read(1, token)
|
||||
self.spi.write(buf)
|
||||
self.spi.write(b'\xff')
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
# check the response
|
||||
if (self.spi.send_recv(0xff)[0] & 0x1f) != 0x05:
|
||||
if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
return
|
||||
|
||||
# wait for write to finish
|
||||
while self.spi.send_recv(0xff)[0] == 0:
|
||||
while self.spi.read(1, 0xff)[0] == 0:
|
||||
pass
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
def write_token(self, token):
|
||||
self.cs.low()
|
||||
self.spi.send(token)
|
||||
self.spi.send(0xff)
|
||||
self.spi.read(1, token)
|
||||
self.spi.write(b'\xff')
|
||||
# wait for write to finish
|
||||
while self.spi.send_recv(0xff)[0] == 0:
|
||||
while self.spi.read(1, 0xff)[0] == 0x00:
|
||||
pass
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
self.spi.write(b'\xff')
|
||||
|
||||
def count(self):
|
||||
return self.sectors
|
||||
@@ -224,7 +244,7 @@ class SDCard:
|
||||
self.readinto(mv[offset : offset + 512])
|
||||
offset += 512
|
||||
nblocks -= 1
|
||||
return self.cmd_nodata(12)
|
||||
return self.cmd_nodata(b'\x0c') # cmd 12
|
||||
return 0
|
||||
|
||||
def writeblocks(self, block_num, buf):
|
||||
@@ -236,7 +256,7 @@ class SDCard:
|
||||
return 1
|
||||
|
||||
# send the data
|
||||
self.write(TOKEN_DATA, buf)
|
||||
self.write(_TOKEN_DATA, buf)
|
||||
else:
|
||||
# CMD25: set write address for first block
|
||||
if self.cmd(25, block_num * self.cdv, 0) != 0:
|
||||
@@ -245,8 +265,8 @@ class SDCard:
|
||||
offset = 0
|
||||
mv = memoryview(buf)
|
||||
while nblocks:
|
||||
self.write(TOKEN_CMD25, mv[offset : offset + 512])
|
||||
self.write(_TOKEN_CMD25, mv[offset : offset + 512])
|
||||
offset += 512
|
||||
nblocks -= 1
|
||||
self.write_token(TOKEN_STOP_TRAN)
|
||||
self.write_token(_TOKEN_STOP_TRAN)
|
||||
return 0
|
||||
|
||||
@@ -5,19 +5,20 @@ QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h
|
||||
|
||||
MICROPY_PY_USSL = 1
|
||||
MICROPY_SSL_AXTLS = 1
|
||||
MICROPY_FATFS = 1
|
||||
MICROPY_PY_BTREE = 1
|
||||
|
||||
FROZEN_DIR = scripts
|
||||
FROZEN_MPY_DIR = modules
|
||||
|
||||
# include py core make definitions
|
||||
include ../py/py.mk
|
||||
|
||||
MPY_CROSS = ../mpy-cross/mpy-cross
|
||||
MPY_TOOL = ../tools/mpy-tool.py
|
||||
MAKE_FROZEN = ../tools/make-frozen.py
|
||||
|
||||
SCRIPTDIR = scripts
|
||||
FROZEN_MPY_DIR = modules
|
||||
FWBIN = $(BUILD)/firmware-combined.bin
|
||||
PORT ?= /dev/ttyACM0
|
||||
BAUD ?= 115200
|
||||
FLASH_MODE ?= qio
|
||||
FLASH_SIZE ?= detect
|
||||
CROSS_COMPILE = xtensa-lx106-elf-
|
||||
ESP_SDK = $(shell $(CC) -print-sysroot)/usr
|
||||
|
||||
@@ -43,7 +44,8 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
|
||||
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
|
||||
$(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
|
||||
LDFLAGS = -nostdlib -T esp8266.ld -Map=$(@:.elf=.map) --cref
|
||||
LDSCRIPT = esp8266.ld
|
||||
LDFLAGS = -nostdlib -T $(LDSCRIPT) -Map=$(@:.elf=.map) --cref
|
||||
LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD)
|
||||
|
||||
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||
@@ -64,6 +66,7 @@ SRC_C = \
|
||||
main.c \
|
||||
help.c \
|
||||
esp_mphal.c \
|
||||
esp_init_data.c \
|
||||
gccollect.c \
|
||||
lexerstr32.c \
|
||||
uart.c \
|
||||
@@ -73,22 +76,23 @@ SRC_C = \
|
||||
espapa102.c \
|
||||
intr.c \
|
||||
modpyb.c \
|
||||
modpybpin.c \
|
||||
modpybpwm.c \
|
||||
modpybrtc.c \
|
||||
modpybadc.c \
|
||||
modpybuart.c \
|
||||
modpybspi.c \
|
||||
modmachine.c \
|
||||
machine_pin.c \
|
||||
machine_pwm.c \
|
||||
machine_rtc.c \
|
||||
machine_adc.c \
|
||||
machine_uart.c \
|
||||
machine_wdt.c \
|
||||
machine_hspi.c \
|
||||
modesp.c \
|
||||
modnetwork.c \
|
||||
modutime.c \
|
||||
moduos.c \
|
||||
modmachine.c \
|
||||
modonewire.c \
|
||||
ets_alt_task.c \
|
||||
$(BUILD)/frozen.c \
|
||||
fatfs_port.c \
|
||||
axtls_helpers.c \
|
||||
hspi.c \
|
||||
$(SRC_MOD)
|
||||
|
||||
STM_SRC_C = $(addprefix stmhal/,\
|
||||
@@ -125,11 +129,15 @@ LIB_SRC_C = $(addprefix lib/,\
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
fatfs/ff.c \
|
||||
fatfs/option/ccsbcs.c \
|
||||
utils/interrupt_char.c \
|
||||
)
|
||||
|
||||
ifeq ($(MICROPY_FATFS), 1)
|
||||
LIB_SRC_C += \
|
||||
lib/fatfs/ff.c \
|
||||
lib/fatfs/option/ccsbcs.c
|
||||
endif
|
||||
|
||||
DRIVERS_SRC_C = $(addprefix drivers/,\
|
||||
dht/dht.c \
|
||||
)
|
||||
@@ -137,9 +145,6 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
|
||||
SRC_S = \
|
||||
gchelper.s \
|
||||
|
||||
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
|
||||
OBJ =
|
||||
OBJ += $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
@@ -148,7 +153,6 @@ OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
|
||||
OBJ += $(BUILD)/$(BUILD)/frozen_mpy.o
|
||||
#OBJ += $(BUILD)/pins_$(BOARD).o
|
||||
|
||||
# List of sources for qstr extraction
|
||||
@@ -156,54 +160,51 @@ SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C)
|
||||
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
all: $(BUILD)/libaxtls.a $(BUILD)/firmware-combined.bin
|
||||
all: $(BUILD)/libaxtls.a $(FWBIN)
|
||||
|
||||
CONFVARS_FILE = $(BUILD)/confvars
|
||||
|
||||
ifeq ($(wildcard $(CONFVARS_FILE)),)
|
||||
$(shell $(MKDIR) -p $(BUILD))
|
||||
$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE))
|
||||
else ifneq ($(shell cat $(CONFVARS_FILE)), $(SCRIPTDIR) $(UART_OS))
|
||||
$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE))
|
||||
$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE))
|
||||
else ifneq ($(shell cat $(CONFVARS_FILE)), $(FROZEN_DIR) $(UART_OS))
|
||||
$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE))
|
||||
endif
|
||||
|
||||
$(BUILD)/uart.o: $(CONFVARS_FILE)
|
||||
|
||||
$(BUILD)/frozen.c: $(wildcard $(SCRIPTDIR)/*) $(CONFVARS_FILE)
|
||||
$(ECHO) "Generating $@"
|
||||
$(Q)$(MAKE_FROZEN) $(SCRIPTDIR) > $@
|
||||
|
||||
# to build .mpy files from .py files
|
||||
$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py
|
||||
@$(ECHO) "MPY $<"
|
||||
$(Q)$(MKDIR) -p $(dir $@)
|
||||
$(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
|
||||
|
||||
# to build frozen_mpy.c from all .mpy files
|
||||
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
|
||||
@$(ECHO) "Creating $@"
|
||||
$(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@
|
||||
FROZEN_EXTRA_DEPS = $(CONFVARS_FILE)
|
||||
|
||||
.PHONY: deploy
|
||||
|
||||
deploy: $(BUILD)/firmware-combined.bin
|
||||
$(ECHO) "Writing $< to the board"
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=8m 0 $<
|
||||
#$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --flash_size=8m 0 $(BUILD)/firmware.elf-0x00000.bin 0x9000 $(BUILD)/firmware.elf-0x0[1-f]000.bin
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=$(FLASH_SIZE) --flash_mode=$(FLASH_MODE) 0 $<
|
||||
|
||||
erase:
|
||||
$(ECHO) "Erase flash"
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) erase_flash
|
||||
|
||||
reset:
|
||||
echo -e "\r\nimport machine; machine.reset()\r\n" >$(PORT)
|
||||
|
||||
$(BUILD)/firmware-combined.bin: $(BUILD)/firmware.elf
|
||||
$(FWBIN): $(BUILD)/firmware.elf
|
||||
$(ECHO) "Create $@"
|
||||
$(Q)esptool.py elf2image $^
|
||||
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x0[1-f]000.bin $@
|
||||
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x[0-5][1-f]000.bin $@
|
||||
|
||||
$(BUILD)/firmware.elf: $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
512k:
|
||||
$(MAKE) LDSCRIPT=esp8266_512k.ld CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_512k.h>"' MICROPY_FATFS=0 MICROPY_PY_BTREE=0
|
||||
|
||||
ota:
|
||||
rm -f $(BUILD)/firmware.elf $(BUILD)/firmware.elf*.bin
|
||||
$(MAKE) LDSCRIPT=esp8266_ota.ld FWBIN=$(BUILD)/firmware-ota.bin
|
||||
|
||||
#MAKE_PINS = boards/make-pins.py
|
||||
#BOARD_PINS = boards/$(BOARD)/pins.csv
|
||||
#AF_FILE = boards/stm32f4xx_af.csv
|
||||
|
||||
@@ -70,12 +70,14 @@ $ make deploy
|
||||
```
|
||||
This will use the `esptool.py` script to download the images. You must have
|
||||
your ESP module in the bootloader mode, and connected to a serial port on your PC.
|
||||
The default serial port is `/dev/ttyACM0`. To specify another, use, eg:
|
||||
The default serial port is `/dev/ttyACM0`, flash mode is `qio` and flash size is
|
||||
`detect` (auto-detect based on Flash ID). To specify other values, use, eg (note
|
||||
that flash size is in megabits):
|
||||
```bash
|
||||
$ make PORT=/dev/ttyUSB0 deploy
|
||||
$ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy
|
||||
```
|
||||
|
||||
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.
|
||||
The image produced is `build/firmware-combined.bin`, to be flashed at 0x00000.
|
||||
|
||||
First start
|
||||
-----------
|
||||
|
||||
@@ -20,7 +20,7 @@ PHDRS
|
||||
irom0_0_phdr PT_LOAD;
|
||||
}
|
||||
|
||||
ENTRY(call_user_start)
|
||||
ENTRY(firmware_start)
|
||||
EXTERN(_DebugExceptionVector)
|
||||
EXTERN(_DoubleExceptionVector)
|
||||
EXTERN(_KernelExceptionVector)
|
||||
@@ -88,9 +88,11 @@ SECTIONS
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/persistentcode*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/reader*.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
@@ -130,18 +132,24 @@ SECTIONS
|
||||
|
||||
*stmhal/pybstdio.o(.literal*, .text*)
|
||||
|
||||
build/main.o(.literal* .text*)
|
||||
*gccollect.o(.literal* .text*)
|
||||
*gchelper.o(.literal* .text*)
|
||||
*help.o(.literal* .text*)
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*modpybpin.o(.literal*, .text*)
|
||||
*modpybpwm.o(.literal*, .text*)
|
||||
*modpybrtc.o(.literal*, .text*)
|
||||
*modpybadc.o(.literal*, .text*)
|
||||
*modpybuart.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modpybspi.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
*moduos.o(.literal* .text*)
|
||||
@@ -196,7 +204,8 @@ SECTIONS
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.literal .text .literal.* .text.* .iram0.literal .iram0.text .iram0.text.*.literal .iram0.text.*)
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
|
||||
305
esp8266/esp8266_512k.ld
Normal file
305
esp8266/esp8266_512k.ld
Normal file
@@ -0,0 +1,305 @@
|
||||
/* GNU linker script for ESP8266 */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
dport0_0_seg : org = 0x3ff00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x40100000, len = 0x8000
|
||||
irom0_0_seg : org = 0x40209000, len = 0x72000
|
||||
}
|
||||
|
||||
/* define the top of RAM */
|
||||
_heap_end = ORIGIN(dram0_0_seg) + LENGTH(dram0_0_seg);
|
||||
|
||||
PHDRS
|
||||
{
|
||||
dport0_0_phdr PT_LOAD;
|
||||
dram0_0_phdr PT_LOAD;
|
||||
dram0_0_bss_phdr PT_LOAD;
|
||||
iram1_0_phdr PT_LOAD;
|
||||
irom0_0_phdr PT_LOAD;
|
||||
}
|
||||
|
||||
ENTRY(firmware_start)
|
||||
EXTERN(_DebugExceptionVector)
|
||||
EXTERN(_DoubleExceptionVector)
|
||||
EXTERN(_KernelExceptionVector)
|
||||
EXTERN(_NMIExceptionVector)
|
||||
EXTERN(_UserExceptionVector)
|
||||
|
||||
PROVIDE(_memmap_vecbase_reset = 0x40000000);
|
||||
|
||||
/* Various memory-map dependent cache attribute settings: */
|
||||
_memmap_cacheattr_wb_base = 0x00000110;
|
||||
_memmap_cacheattr_wt_base = 0x00000110;
|
||||
_memmap_cacheattr_bp_base = 0x00000220;
|
||||
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
|
||||
_memmap_cacheattr_wb_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wba_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wt_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_bp_trapnull = 0x2222222F;
|
||||
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
|
||||
_memmap_cacheattr_wb_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_wt_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_bp_allvalid = 0x22222222;
|
||||
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.dport0.rodata : ALIGN(4)
|
||||
{
|
||||
_dport0_rodata_start = ABSOLUTE(.);
|
||||
*(.dport0.rodata)
|
||||
*(.dport.rodata)
|
||||
_dport0_rodata_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.literal : ALIGN(4)
|
||||
{
|
||||
_dport0_literal_start = ABSOLUTE(.);
|
||||
*(.dport0.literal)
|
||||
*(.dport.literal)
|
||||
_dport0_literal_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.data : ALIGN(4)
|
||||
{
|
||||
_dport0_data_start = ABSOLUTE(.);
|
||||
*(.dport0.data)
|
||||
*(.dport.data)
|
||||
_dport0_data_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.irom0.text : ALIGN(4)
|
||||
{
|
||||
_irom0_text_start = ABSOLUTE(.);
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
|
||||
/* we put some specific text in this section */
|
||||
|
||||
*py/argcheck.o*(.literal* .text*)
|
||||
*py/asm*.o*(.literal* .text*)
|
||||
*py/bc.o*(.literal* .text*)
|
||||
*py/binary.o*(.literal* .text*)
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/persistentcode*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/reader*.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
*py/mod*.o*(.literal* .text*)
|
||||
*py/mpprint.o*(.literal* .text*)
|
||||
*py/mpstate.o*(.literal* .text*)
|
||||
*py/mpz.o*(.literal* .text*)
|
||||
*py/native*.o*(.literal* .text*)
|
||||
*py/nlr*.o*(.literal* .text*)
|
||||
*py/obj*.o*(.literal* .text*)
|
||||
*py/opmethods.o*(.literal* .text*)
|
||||
*py/parse*.o*(.literal* .text*)
|
||||
*py/qstr.o*(.literal* .text*)
|
||||
*py/repl.o*(.literal* .text*)
|
||||
*py/runtime.o*(.literal* .text*)
|
||||
*py/scope.o*(.literal* .text*)
|
||||
*py/sequence.o*(.literal* .text*)
|
||||
*py/showbc.o*(.literal* .text*)
|
||||
*py/smallint.o*(.literal* .text*)
|
||||
*py/stackctrl.o*(.literal* .text*)
|
||||
*py/stream.o*(.literal* .text*)
|
||||
*py/unicode.o*(.literal* .text*)
|
||||
*py/vm.o*(.literal* .text*)
|
||||
*py/vstr.o*(.literal* .text*)
|
||||
*py/warning.o*(.literal* .text*)
|
||||
|
||||
*extmod/*.o*(.literal* .text*)
|
||||
|
||||
*lib/fatfs/*.o*(.literal*, .text*)
|
||||
*/libaxtls.a:(.literal*, .text*)
|
||||
*lib/berkeley-db-1.xx/*.o(.literal*, .text*)
|
||||
*lib/libm/*.o*(.literal*, .text*)
|
||||
*lib/mp-readline/*.o(.literal*, .text*)
|
||||
*lib/netutils/*.o*(.literal*, .text*)
|
||||
*lib/timeutils/*.o*(.literal*, .text*)
|
||||
*lib/utils/*.o*(.literal*, .text*)
|
||||
|
||||
*stmhal/pybstdio.o(.literal*, .text*)
|
||||
|
||||
build/main.o(.literal* .text*)
|
||||
*gccollect.o(.literal* .text*)
|
||||
*gchelper.o(.literal* .text*)
|
||||
*help.o(.literal* .text*)
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
*moduos.o(.literal* .text*)
|
||||
*modutime.o(.literal* .text*)
|
||||
*modlwip.o(.literal* .text*)
|
||||
*modsocket.o(.literal* .text*)
|
||||
*modonewire.o(.literal* .text*)
|
||||
|
||||
/* we put as much rodata as possible in this section */
|
||||
/* note that only rodata accessed as a machine word is allowed here */
|
||||
*py/qstr.o(.rodata.const_pool)
|
||||
*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
|
||||
*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
|
||||
*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
|
||||
*/frozen.o(.rodata.mp_frozen_sizes) /* frozen modules */
|
||||
*/frozen.o(.rodata.mp_frozen_content) /* frozen modules */
|
||||
|
||||
/* for -mforce-l32 */
|
||||
build/*.o(.rodata*)
|
||||
|
||||
_irom0_text_end = ABSOLUTE(.);
|
||||
} >irom0_0_seg :irom0_0_phdr
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.UserEnter.text)
|
||||
. = ALIGN(16);
|
||||
*(.DebugExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.NMIExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.KernelExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.UserExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.DoubleExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
*(.literal .text .literal.* .text.* .iram0.literal .iram0.text .iram0.text.*.literal .iram0.text.*)
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.lit4 : ALIGN(4)
|
||||
{
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.sdk.version)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame)
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
*(.gnu.linkonce.h.*)
|
||||
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
. = ALIGN(4); /* this table MUST be 4-byte aligned */
|
||||
_bss_table_start = ABSOLUTE(.);
|
||||
LONG(_bss_start)
|
||||
LONG(_bss_end)
|
||||
_bss_table_end = ABSOLUTE(.);
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_bss_phdr
|
||||
}
|
||||
|
||||
/* get ROM code address */
|
||||
INCLUDE "eagle.rom.addr.v6.ld"
|
||||
306
esp8266/esp8266_ota.ld
Normal file
306
esp8266/esp8266_ota.ld
Normal file
@@ -0,0 +1,306 @@
|
||||
/* GNU linker script for ESP8266 */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
dport0_0_seg : org = 0x3ff00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x40100000, len = 0x8000
|
||||
/* 0x3c000 is size of bootloader, 0x9000 is size of packed RAM segments */
|
||||
irom0_0_seg : org = 0x40200000 + 0x3c000 + 0x9000, len = 0x87000
|
||||
}
|
||||
|
||||
/* define the top of RAM */
|
||||
_heap_end = ORIGIN(dram0_0_seg) + LENGTH(dram0_0_seg);
|
||||
|
||||
PHDRS
|
||||
{
|
||||
dport0_0_phdr PT_LOAD;
|
||||
dram0_0_phdr PT_LOAD;
|
||||
dram0_0_bss_phdr PT_LOAD;
|
||||
iram1_0_phdr PT_LOAD;
|
||||
irom0_0_phdr PT_LOAD;
|
||||
}
|
||||
|
||||
ENTRY(firmware_start)
|
||||
EXTERN(_DebugExceptionVector)
|
||||
EXTERN(_DoubleExceptionVector)
|
||||
EXTERN(_KernelExceptionVector)
|
||||
EXTERN(_NMIExceptionVector)
|
||||
EXTERN(_UserExceptionVector)
|
||||
|
||||
PROVIDE(_memmap_vecbase_reset = 0x40000000);
|
||||
|
||||
/* Various memory-map dependent cache attribute settings: */
|
||||
_memmap_cacheattr_wb_base = 0x00000110;
|
||||
_memmap_cacheattr_wt_base = 0x00000110;
|
||||
_memmap_cacheattr_bp_base = 0x00000220;
|
||||
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
|
||||
_memmap_cacheattr_wb_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wba_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wt_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_bp_trapnull = 0x2222222F;
|
||||
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
|
||||
_memmap_cacheattr_wb_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_wt_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_bp_allvalid = 0x22222222;
|
||||
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.dport0.rodata : ALIGN(4)
|
||||
{
|
||||
_dport0_rodata_start = ABSOLUTE(.);
|
||||
*(.dport0.rodata)
|
||||
*(.dport.rodata)
|
||||
_dport0_rodata_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.literal : ALIGN(4)
|
||||
{
|
||||
_dport0_literal_start = ABSOLUTE(.);
|
||||
*(.dport0.literal)
|
||||
*(.dport.literal)
|
||||
_dport0_literal_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.data : ALIGN(4)
|
||||
{
|
||||
_dport0_data_start = ABSOLUTE(.);
|
||||
*(.dport0.data)
|
||||
*(.dport.data)
|
||||
_dport0_data_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.irom0.text : ALIGN(4)
|
||||
{
|
||||
_irom0_text_start = ABSOLUTE(.);
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
|
||||
/* we put some specific text in this section */
|
||||
|
||||
*py/argcheck.o*(.literal* .text*)
|
||||
*py/asm*.o*(.literal* .text*)
|
||||
*py/bc.o*(.literal* .text*)
|
||||
*py/binary.o*(.literal* .text*)
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/persistentcode*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/reader*.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
*py/mod*.o*(.literal* .text*)
|
||||
*py/mpprint.o*(.literal* .text*)
|
||||
*py/mpstate.o*(.literal* .text*)
|
||||
*py/mpz.o*(.literal* .text*)
|
||||
*py/native*.o*(.literal* .text*)
|
||||
*py/nlr*.o*(.literal* .text*)
|
||||
*py/obj*.o*(.literal* .text*)
|
||||
*py/opmethods.o*(.literal* .text*)
|
||||
*py/parse*.o*(.literal* .text*)
|
||||
*py/qstr.o*(.literal* .text*)
|
||||
*py/repl.o*(.literal* .text*)
|
||||
*py/runtime.o*(.literal* .text*)
|
||||
*py/scope.o*(.literal* .text*)
|
||||
*py/sequence.o*(.literal* .text*)
|
||||
*py/showbc.o*(.literal* .text*)
|
||||
*py/smallint.o*(.literal* .text*)
|
||||
*py/stackctrl.o*(.literal* .text*)
|
||||
*py/stream.o*(.literal* .text*)
|
||||
*py/unicode.o*(.literal* .text*)
|
||||
*py/vm.o*(.literal* .text*)
|
||||
*py/vstr.o*(.literal* .text*)
|
||||
*py/warning.o*(.literal* .text*)
|
||||
|
||||
*extmod/*.o*(.literal* .text*)
|
||||
|
||||
*lib/fatfs/*.o*(.literal*, .text*)
|
||||
*/libaxtls.a:(.literal*, .text*)
|
||||
*lib/berkeley-db-1.xx/*.o(.literal*, .text*)
|
||||
*lib/libm/*.o*(.literal*, .text*)
|
||||
*lib/mp-readline/*.o(.literal*, .text*)
|
||||
*lib/netutils/*.o*(.literal*, .text*)
|
||||
*lib/timeutils/*.o*(.literal*, .text*)
|
||||
*lib/utils/*.o*(.literal*, .text*)
|
||||
|
||||
*stmhal/pybstdio.o(.literal*, .text*)
|
||||
|
||||
build/main.o(.literal* .text*)
|
||||
*gccollect.o(.literal* .text*)
|
||||
*gchelper.o(.literal* .text*)
|
||||
*help.o(.literal* .text*)
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
*moduos.o(.literal* .text*)
|
||||
*modutime.o(.literal* .text*)
|
||||
*modlwip.o(.literal* .text*)
|
||||
*modsocket.o(.literal* .text*)
|
||||
*modonewire.o(.literal* .text*)
|
||||
|
||||
/* we put as much rodata as possible in this section */
|
||||
/* note that only rodata accessed as a machine word is allowed here */
|
||||
*py/qstr.o(.rodata.const_pool)
|
||||
*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
|
||||
*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
|
||||
*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
|
||||
*/frozen.o(.rodata.mp_frozen_sizes) /* frozen modules */
|
||||
*/frozen.o(.rodata.mp_frozen_content) /* frozen modules */
|
||||
|
||||
/* for -mforce-l32 */
|
||||
build/*.o(.rodata*)
|
||||
|
||||
_irom0_text_end = ABSOLUTE(.);
|
||||
} >irom0_0_seg :irom0_0_phdr
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.UserEnter.text)
|
||||
. = ALIGN(16);
|
||||
*(.DebugExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.NMIExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.KernelExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.UserExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.DoubleExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
*(.literal .text .literal.* .text.* .iram0.literal .iram0.text .iram0.text.*.literal .iram0.text.*)
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.lit4 : ALIGN(4)
|
||||
{
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.sdk.version)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame)
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
*(.gnu.linkonce.h.*)
|
||||
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
. = ALIGN(4); /* this table MUST be 4-byte aligned */
|
||||
_bss_table_start = ABSOLUTE(.);
|
||||
LONG(_bss_start)
|
||||
LONG(_bss_end)
|
||||
_bss_table_end = ABSOLUTE(.);
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_bss_phdr
|
||||
}
|
||||
|
||||
/* get ROM code address */
|
||||
INCLUDE "eagle.rom.addr.v6.ld"
|
||||
77
esp8266/esp_init_data.c
Normal file
77
esp8266/esp_init_data.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ets_sys.h"
|
||||
#include "etshal.h"
|
||||
#include "esp_mphal.h"
|
||||
#include "user_interface.h"
|
||||
#include "extmod/misc.h"
|
||||
|
||||
NORETURN void call_user_start(void);
|
||||
void ets_printf(const char *fmt, ...);
|
||||
extern char flashchip;
|
||||
|
||||
static const uint8_t default_init_data[] __attribute__((aligned(4))) = {
|
||||
0x05, 0x00, 0x04, 0x02, 0x05, 0x05, 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, 0x05, 0x04, 0x05, 0x05,
|
||||
0x04, 0xfe, 0xfd, 0xff, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0x0a, 0xff, 0xff, 0xf8, 0x00,
|
||||
0xf8, 0xf8, 0x52, 0x4e, 0x4a, 0x44, 0x40, 0x38, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xe1, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x93, 0x43, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void firmware_start(void) {
|
||||
// For SDK 1.5.2, either address has shifted and not mirrored in
|
||||
// eagle.rom.addr.v6.ld, or extra initial member was added.
|
||||
SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4);
|
||||
|
||||
char buf[128];
|
||||
SPIRead(flash->chip_size - 4 * 0x1000, buf, sizeof(buf));
|
||||
/*for (int i = 0; i < sizeof(buf); i++) {
|
||||
static char hexf[] = "%x ";
|
||||
ets_printf(hexf, buf[i]);
|
||||
}*/
|
||||
|
||||
bool inited = false;
|
||||
for (int i = 0; i < sizeof(buf); i++) {
|
||||
if (buf[i] != 0xff) {
|
||||
inited = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inited) {
|
||||
static char msg[] = "Writing init data\n";
|
||||
ets_printf(msg);
|
||||
SPIRead((uint32_t)&default_init_data - 0x40200000, buf, sizeof(buf));
|
||||
SPIWrite(flash->chip_size - 4 * 0x1000, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
asm("j call_user_start");
|
||||
}
|
||||
@@ -36,17 +36,13 @@
|
||||
#include "extmod/misc.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
|
||||
extern void ets_wdt_disable(void);
|
||||
extern void wdt_feed(void);
|
||||
extern void ets_delay_us();
|
||||
|
||||
STATIC byte input_buf_array[256];
|
||||
ringbuf_t input_buf = {input_buf_array, sizeof(input_buf_array)};
|
||||
void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len);
|
||||
const mp_print_t mp_debug_print = {NULL, mp_hal_debug_tx_strn_cooked};
|
||||
|
||||
void mp_hal_init(void) {
|
||||
ets_wdt_disable(); // it's a pain while developing
|
||||
//ets_wdt_disable(); // it's a pain while developing
|
||||
mp_hal_rtc_init();
|
||||
uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200);
|
||||
}
|
||||
@@ -64,7 +60,14 @@ int mp_hal_stdin_rx_chr(void) {
|
||||
if (c != -1) {
|
||||
return c;
|
||||
}
|
||||
#if 0
|
||||
// Idles CPU but need more testing before enabling
|
||||
if (!ets_loop_iter()) {
|
||||
asm("waiti 0");
|
||||
}
|
||||
#else
|
||||
mp_hal_delay_us(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +117,7 @@ void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) {
|
||||
}
|
||||
|
||||
uint32_t mp_hal_ticks_ms(void) {
|
||||
return system_get_time() / 1000;
|
||||
return ((uint64_t)system_time_high_word << 32 | (uint64_t)system_get_time()) / 1000;
|
||||
}
|
||||
|
||||
uint32_t mp_hal_ticks_us(void) {
|
||||
@@ -125,14 +128,6 @@ void mp_hal_delay_ms(uint32_t delay) {
|
||||
mp_hal_delay_us(delay * 1000);
|
||||
}
|
||||
|
||||
void mp_hal_set_interrupt_char(int c) {
|
||||
if (c != -1) {
|
||||
mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception));
|
||||
}
|
||||
extern int interrupt_char;
|
||||
interrupt_char = c;
|
||||
}
|
||||
|
||||
void ets_event_poll(void) {
|
||||
ets_loop_iter();
|
||||
if (MP_STATE_VM(mp_pending_exception) != NULL) {
|
||||
@@ -177,7 +172,7 @@ static int call_dupterm_read(void) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(MP_STATE_PORT(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
|
||||
nlr_pop();
|
||||
if (*(byte*)bufinfo.buf == interrupt_char) {
|
||||
if (*(byte*)bufinfo.buf == mp_interrupt_char) {
|
||||
mp_keyboard_interrupt();
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
#define _INCLUDED_MPHAL_H_
|
||||
|
||||
#include "py/ringbuf.h"
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "xtirq.h"
|
||||
|
||||
void mp_keyboard_interrupt(void);
|
||||
extern int interrupt_char;
|
||||
|
||||
struct _mp_print_t;
|
||||
// Structure for UART-only output via mp_printf()
|
||||
@@ -75,9 +75,11 @@ void ets_event_poll(void);
|
||||
// C-level pin HAL
|
||||
#include "etshal.h"
|
||||
#include "gpio.h"
|
||||
#include "esp8266/modpyb.h"
|
||||
#include "esp8266/modmachine.h"
|
||||
#define MP_HAL_PIN_FMT "%u"
|
||||
#define mp_hal_pin_obj_t uint32_t
|
||||
#define mp_hal_get_pin_obj(o) mp_obj_get_pin(o)
|
||||
#define mp_hal_pin_name(p) (p)
|
||||
void mp_hal_pin_input(mp_hal_pin_obj_t pin);
|
||||
void mp_hal_pin_output(mp_hal_pin_obj_t pin);
|
||||
void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin);
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
|
||||
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_ESP8266_NEOPIXEL
|
||||
|
||||
#include "c_types.h"
|
||||
#include "eagle_soc.h"
|
||||
#include "user_interface.h"
|
||||
@@ -30,7 +33,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
||||
#ifdef NEO_KHZ400
|
||||
if(is800KHz) {
|
||||
#endif
|
||||
time0 = fcpu / 2500000; // 0.4us
|
||||
time0 = fcpu / 2857143; // 0.35us
|
||||
time1 = fcpu / 1250000; // 0.8us
|
||||
period = fcpu / 800000; // 1.25us per bit
|
||||
#ifdef NEO_KHZ400
|
||||
@@ -41,6 +44,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t irq_state = mp_hal_quiet_timing_enter();
|
||||
for(t = time0;; t = time0) {
|
||||
if(pix & mask) t = time1; // Bit high duration
|
||||
while(((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start
|
||||
@@ -55,4 +59,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
||||
}
|
||||
}
|
||||
while((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit
|
||||
mp_hal_quiet_timing_exit(irq_state);
|
||||
}
|
||||
|
||||
#endif // MICROPY_ESP8266_NEOPIXEL
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "etshal.h"
|
||||
#include "user_interface.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
#include "esponewire.h"
|
||||
|
||||
#define TIMING_RESET1 (0)
|
||||
|
||||
@@ -87,7 +87,7 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
|
||||
if (emu_tasks[id].i_put == -1) {
|
||||
// queue is full
|
||||
printf("ets_post: task %d queue full\n", prio);
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
q = &q[emu_tasks[id].i_put++];
|
||||
q->sig = sig;
|
||||
@@ -104,16 +104,28 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
|
||||
|
||||
ets_intr_unlock();
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ets_loop_iter_disable = 0;
|
||||
|
||||
// to implement a 64-bit wide microsecond counter
|
||||
static uint32_t system_time_prev = 0;
|
||||
uint32_t system_time_high_word = 0;
|
||||
|
||||
bool ets_loop_iter(void) {
|
||||
if (ets_loop_iter_disable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// handle overflow of system microsecond counter
|
||||
uint32_t system_time_cur = system_get_time();
|
||||
if (system_time_cur < system_time_prev) {
|
||||
system_time_high_word += 1; // record overflow of low 32-bits
|
||||
}
|
||||
system_time_prev = system_time_cur;
|
||||
|
||||
//static unsigned cnt;
|
||||
bool progress = false;
|
||||
for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) {
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
extern int ets_loop_iter_disable;
|
||||
extern uint32_t system_time_high_word;
|
||||
|
||||
bool ets_loop_iter(void);
|
||||
|
||||
@@ -20,8 +20,13 @@ void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_mi
|
||||
void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data);
|
||||
void ets_timer_disarm(os_timer_t *tim);
|
||||
|
||||
extern void ets_wdt_disable(void);
|
||||
extern void wdt_feed(void);
|
||||
|
||||
// Opaque structure
|
||||
typedef char MD5_CTX[64];
|
||||
#ifndef MD5_CTX
|
||||
typedef char MD5_CTX[88];
|
||||
#endif
|
||||
|
||||
void MD5Init(MD5_CTX *context);
|
||||
void MD5Update(MD5_CTX *context, const void *data, unsigned int len);
|
||||
@@ -29,6 +34,12 @@ void MD5Final(unsigned char digest[16], MD5_CTX *context);
|
||||
|
||||
// These prototypes are for recent SDKs with "malloc tracking"
|
||||
void *pvPortMalloc(unsigned sz, const char *fname, int line);
|
||||
void *pvPortZalloc(unsigned sz, const char *fname, int line);
|
||||
void *pvPortRealloc(void *p, unsigned sz, const char *fname, int line);
|
||||
void vPortFree(void *p, const char *fname, int line);
|
||||
|
||||
uint32_t SPIRead(uint32_t offset, void *buf, uint32_t len);
|
||||
uint32_t SPIWrite(uint32_t offset, const void *buf, uint32_t len);
|
||||
uint32_t SPIEraseSector(int sector);
|
||||
|
||||
#endif // _INCLUDED_ETSHAL_H_
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "py/obj.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "timeutils.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
DWORD get_fattime(void) {
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ void gc_collect(void) {
|
||||
// trace the stack, including the registers (since they live on the stack in this function)
|
||||
gc_collect_root((void**)sp, (STACK_END - sp) / sizeof(uint32_t));
|
||||
|
||||
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
|
||||
// trace any native code because it can contain pointers to the heap
|
||||
esp_native_code_gc_collect();
|
||||
#endif
|
||||
|
||||
// end the GC
|
||||
gc_collect_end();
|
||||
}
|
||||
|
||||
@@ -38,3 +38,4 @@ extern uint32_t _heap_start;
|
||||
extern uint32_t _heap_end;
|
||||
|
||||
void gc_collect(void);
|
||||
void esp_native_code_gc_collect(void);
|
||||
|
||||
331
esp8266/hspi.c
Normal file
331
esp8266/hspi.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 David Ogilvy (MetalPhreak)
|
||||
* Modified 2016 by Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hspi.h"
|
||||
|
||||
/*
|
||||
Wrapper to setup HSPI/SPI GPIO pins and default SPI clock
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
Not used in Micropython.
|
||||
*/
|
||||
void spi_init(uint8_t spi_no) {
|
||||
spi_init_gpio(spi_no, SPI_CLK_USE_DIV);
|
||||
spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV);
|
||||
spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
|
||||
spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
|
||||
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Configures SPI mode parameters for clock edge and clock polarity.
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
spi_cpha - (0) Data is valid on clock leading edge
|
||||
(1) Data is valid on clock trailing edge
|
||||
spi_cpol - (0) Clock is low when inactive
|
||||
(1) Clock is high when inactive
|
||||
For Micropython this version is different from original.
|
||||
*/
|
||||
void spi_mode(uint8_t spi_no, uint8_t spi_cpha, uint8_t spi_cpol) {
|
||||
if (spi_cpol) {
|
||||
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
|
||||
}
|
||||
if (spi_cpha == spi_cpol) {
|
||||
// Mode 3 - MOSI is set on falling edge of clock
|
||||
// Mode 0 - MOSI is set on falling edge of clock
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
|
||||
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
|
||||
} else {
|
||||
// Mode 2 - MOSI is set on rising edge of clock
|
||||
// Mode 1 - MOSI is set on rising edge of clock
|
||||
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Initialise the GPIO pins for use as SPI pins.
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
sysclk_as_spiclk -
|
||||
SPI_CLK_80MHZ_NODIV (1) if using 80MHz for SPI clock.
|
||||
SPI_CLK_USE_DIV (0) if using divider for lower speed.
|
||||
*/
|
||||
void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk) {
|
||||
uint32_t clock_div_flag = 0;
|
||||
if (sysclk_as_spiclk) {
|
||||
clock_div_flag = 0x0001;
|
||||
}
|
||||
if (spi_no == SPI) {
|
||||
// Set bit 8 if 80MHz sysclock required
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag<<8));
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);
|
||||
} else if (spi_no == HSPI) {
|
||||
// Set bit 9 if 80MHz sysclock required
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag<<9));
|
||||
// GPIO12 is HSPI MISO pin (Master Data In)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
|
||||
// GPIO13 is HSPI MOSI pin (Master Data Out)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
|
||||
// GPIO14 is HSPI CLK pin (Clock)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
|
||||
// GPIO15 is HSPI CS pin (Chip Select / Slave Select)
|
||||
// In Micropython, we are handling CS ourself in drivers.
|
||||
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set up the control registers for the SPI clock
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
prediv - predivider value (actual division value)
|
||||
cntdiv - postdivider value (actual division value)
|
||||
Set either divider to 0 to disable all division (80MHz sysclock)
|
||||
*/
|
||||
void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv) {
|
||||
if (prediv == 0 || cntdiv == 0) {
|
||||
WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK);
|
||||
} else {
|
||||
WRITE_PERI_REG(SPI_CLOCK(spi_no),
|
||||
(((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
|
||||
(((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
|
||||
(((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
|
||||
((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Setup the byte order for shifting data out of buffer
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
byte_order -
|
||||
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
|
||||
Data is sent out starting with Bit31 and down to Bit0
|
||||
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
|
||||
Data is sent out starting with the lowest BYTE, from MSB to LSB,
|
||||
followed by the second lowest BYTE, from MSB to LSB, followed by
|
||||
the second highest BYTE, from MSB to LSB, followed by the highest
|
||||
BYTE, from MSB to LSB 0xABCDEFGH would be sent as 0xGHEFCDAB.
|
||||
*/
|
||||
void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order) {
|
||||
if (byte_order) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Setup the byte order for shifting data into buffer
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
byte_order -
|
||||
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
|
||||
Data is read in starting with Bit31 and down to Bit0
|
||||
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
|
||||
Data is read in starting with the lowest BYTE, from MSB to LSB,
|
||||
followed by the second lowest BYTE, from MSB to LSB, followed by
|
||||
the second highest BYTE, from MSB to LSB, followed by the highest
|
||||
BYTE, from MSB to LSB 0xABCDEFGH would be read as 0xGHEFCDAB
|
||||
*/
|
||||
void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order) {
|
||||
if (byte_order) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SPI transaction function
|
||||
spi_no - SPI (0) or HSPI (1)
|
||||
cmd_bits - actual number of bits to transmit
|
||||
cmd_data - command data
|
||||
addr_bits - actual number of bits to transmit
|
||||
addr_data - address data
|
||||
dout_bits - actual number of bits to transmit
|
||||
dout_data - output data
|
||||
din_bits - actual number of bits to receive
|
||||
Returns: read data - uint32_t containing read in data only if RX was set
|
||||
0 - something went wrong (or actual read data was 0)
|
||||
1 - data sent ok (or actual read data is 1)
|
||||
Note: all data is assumed to be stored in the lower bits of the data variables
|
||||
(for anything <32 bits).
|
||||
*/
|
||||
uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
|
||||
uint32_t addr_bits, uint32_t addr_data,
|
||||
uint32_t dout_bits, uint32_t dout_data,
|
||||
uint32_t din_bits, uint32_t dummy_bits) {
|
||||
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
|
||||
|
||||
// Enable SPI Functions
|
||||
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
|
||||
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
|
||||
|
||||
// Enable functions based on number of bits. 0 bits = disabled.
|
||||
// This is rather inefficient but allows for a very generic function.
|
||||
// CMD ADDR and MOSI are set below to save on an extra if statement.
|
||||
if (din_bits) {
|
||||
if (dout_bits) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_DOUTDIN);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
|
||||
}
|
||||
}
|
||||
if (dummy_bits) {
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);
|
||||
}
|
||||
|
||||
// Setup Bitlengths
|
||||
WRITE_PERI_REG(SPI_USER1(spi_no),
|
||||
// Number of bits in Address
|
||||
((addr_bits - 1) & SPI_USR_ADDR_BITLEN) << SPI_USR_ADDR_BITLEN_S |
|
||||
// Number of bits to Send
|
||||
((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
|
||||
// Number of bits to receive
|
||||
((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S |
|
||||
// Number of Dummy bits to insert
|
||||
((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S);
|
||||
|
||||
// Setup Command Data
|
||||
if (cmd_bits) {
|
||||
// Enable COMMAND function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);
|
||||
// Align command data to high bits
|
||||
uint16_t command = cmd_data << (16-cmd_bits);
|
||||
// Swap byte order
|
||||
command = ((command>>8)&0xff) | ((command<<8)&0xff00);
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no), (
|
||||
(((cmd_bits - 1) & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) |
|
||||
(command & SPI_USR_COMMAND_VALUE)
|
||||
));
|
||||
}
|
||||
|
||||
// Setup Address Data
|
||||
if (addr_bits) {
|
||||
// Enable ADDRess function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);
|
||||
// Align address data to high bits
|
||||
WRITE_PERI_REG(SPI_ADDR(spi_no), addr_data << (32 - addr_bits));
|
||||
}
|
||||
|
||||
// Setup DOUT data
|
||||
if (dout_bits) {
|
||||
// Enable MOSI function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
|
||||
// Copy data to W0
|
||||
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_WR_BYTE_ORDER) {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits));
|
||||
} else {
|
||||
uint8_t dout_extra_bits = dout_bits%8;
|
||||
|
||||
if (dout_extra_bits) {
|
||||
// If your data isn't a byte multiple (8/16/24/32 bits) and you
|
||||
// don't have SPI_WR_BYTE_ORDER set, you need this to move the
|
||||
// non-8bit remainder to the MSBs. Not sure if there's even a use
|
||||
// case for this, but it's here if you need it... For example,
|
||||
// 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output
|
||||
// as if it were 0x0DA4, of which 0xA4, and then 0x0 would be
|
||||
// shifted out (first 8 bits of low byte, then 4 MSB bits of high
|
||||
// byte - ie reverse byte order).
|
||||
// The code below shifts it out as 0xA4 followed by 0xD as you
|
||||
// might require.
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), (
|
||||
(0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data)
|
||||
<< (8-dout_extra_bits) |
|
||||
((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits)))
|
||||
& dout_data)
|
||||
));
|
||||
} else {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Begin SPI Transaction
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
|
||||
|
||||
// Return DIN data
|
||||
if (din_bits) {
|
||||
while (spi_busy(spi_no)) {}; // Wait for SPI transaction to complete
|
||||
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) {
|
||||
// Assuming data in is written to MSB. TBC
|
||||
return READ_PERI_REG(SPI_W0(spi_no)) >> (32 - din_bits);
|
||||
} else {
|
||||
// Read in the same way as DOUT is sent. Note existing contents of
|
||||
// SPI_W0 remain unless overwritten!
|
||||
return READ_PERI_REG(SPI_W0(spi_no));
|
||||
}
|
||||
return 0; // Something went wrong
|
||||
}
|
||||
|
||||
// Transaction completed
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Just do minimal work needed to send 8 bits.
|
||||
*/
|
||||
inline void spi_tx8fast(uint8_t spi_no, uint8_t dout_data) {
|
||||
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
|
||||
|
||||
// Enable SPI Functions
|
||||
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
|
||||
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
|
||||
|
||||
// Setup Bitlengths
|
||||
WRITE_PERI_REG(SPI_USER1(spi_no),
|
||||
// Number of bits to Send
|
||||
((8 - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
|
||||
// Number of bits to receive
|
||||
((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S);
|
||||
|
||||
|
||||
// Setup DOUT data
|
||||
// Enable MOSI function in SPI module
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
|
||||
// Copy data to W0
|
||||
if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_WR_BYTE_ORDER) {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - 8));
|
||||
} else {
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
|
||||
}
|
||||
|
||||
// Begin SPI Transaction
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user