Temos uma seção de discussões no Github agora. Quando um problema é definitivamente um defeito central, você reduzirá o tempo necessário para corrigi-lo se criar um problema, já que priorizo os problemas em vez de acompanhar as discussões.
Isso corrige muitos dos bugs presentes no 2.6.x
2.6.x apresenta uma pegada flash serial significativamente aprimorada ao adicionar recursos, o fio pode despertar o escravo do modo de suspensão sem corromper os dados e muito, muito mais, consulte o Changelog.
Somente versões do Arduino IDE baixadas do arduino.cc devem ser usadas, NUNCA de um gerenciador de pacotes Linux. Os gerenciadores de pacotes geralmente possuem o IDE do Arduino – mas o modificaram . Isso ocorre apesar de eles não saberem nada sobre Arduino ou desenvolvimento embarcado em geral, muito menos o que precisariam saber para modificá-lo com sucesso. Essas versões são notórias por problemas sutis, mas sérios, causados por essas modificações imprudentes. Não se deve esperar que este núcleo funcione em tais versões, e nenhuma modificação será feita para corrigir versões do IDE que vêm de gerenciadores de pacotes por esse motivo.
Este é um bug no cliente Arduino.
As versões IDE entre 1.8.13 e 2.x desenvolveram novos defeitos significativos. As versões IDE 1.8.2 e anteriores, no entanto, possuem defeitos incapacitantes não corrigidos. Acredito que eles finalmente tenham uma versão funcional do IDE, e acredito que o mais recente seja capaz de instalar meu núcleo corretamente.
Antes do megaTinyCore 2.6.0, a instalação manual do megaTinyCore causava o travamento da V1.8.14 do IDE devido a esse bug quando você instalava o núcleo manualmente na pasta Arduino. Os usuários da versão 1.8.14 e posterior devem usar a versão 2.6.0 do megaTinyCore.
Compro muita coisa eletrônica no AliExpress. É um ótimo mercado para coisas feitas por empresas chinesas e que são em sua maioria genéricas, incluindo muitos componentes indisponíveis para indivíduos no Ocidente global de qualquer outra forma (por exemplo, o pedido mínimo é um carretel ou algo parecido - se você conseguir encontrar um fornecedor de componentes que trabalha com o fabricante chinês de chips sem nome). Não é um bom lugar para as mais recentes linhas de produtos semicondutores dos principais fabricantes ocidentais, especialmente no meio de uma escassez histórica desses chips. Os dispositivos AVR modernos, quando estão disponíveis através desses canais, são frequentemente relatados como falsos ou defeituosos (como ATtiny412s que pensam que são 416s e podem não executar corretamente a reinicialização ao ligar). Por falar nisso, você provavelmente não vai querer comprar nenhum microcontrolador AVR no AliExpress ... Placas montadas, como os clones do Arduino Nano, geralmente funcionam se você evitar aquelas com chips LGT8 de terceiros e tomar cuidado com aquelas com ATmega168p em vez do '328p - mas há muitos relatos de microcontroladores falsos quando eles são vendidos como chips simples (ouvi falar de ATtiny85s falsos que foram realmente comentados ATtiny13s; não são apenas os AVRs modernos que são falsificados). Existem muitas teorias interessantes sobre a origem desses chips falsos, e a Microchip permaneceu totalmente silenciosa sobre o assunto.
Este documento é melhor visualizado on-line (em vez de abrir o arquivo markdown em seu editor de texto favorito), para que os links sejam clicáveis e as imagens embutidas sejam mostradas e, provavelmente o mais importante, para fazer com que as tabelas sejam renderizadas corretamente às vezes. Novamente, este [documento pode ser encontrado no github](https://github.com/SpenceKonde/megaTinyCore](https://github.com/SpenceKonde/megaTinyCore)
Versões mais antigas não lidam adequadamente com os programadores no menu ferramentas -> programadores, o que degrada a UX rapidamente à medida que o número de núcleos instalados aumenta. Eles não são adequados. As versões mais recentes começando com 1.8.14 (incluindo 1.8.17, 1.8.18 e 1.8.19) podem gerar um erro "pânico: nenhuma versão principal encontrada" porque não conseguem analisar adequadamente o platform.txt. Desde a versão 2.6.0, modificamos manualmente o platform.txt diretamente antes do lançamento, então isso é um problema menor
Quando o megaTinyCore é instalado por meio do gerenciador de placa, a versão necessária do conjunto de ferramentas é instalada automaticamente. Todas as peças da série 0/1/2 são suportadas sem etapas extras. Até 2.2.7, usávamos a versão Arduino7 do avr-gcc (gcc 7.3.0 e avrlibc 3.6.1) com os ATpacks mais recentes em junho de 2020. A partir de 2.2.7, começamos a usar minha versão Azduino do conjunto de ferramentas, que atualizou ATpacks para todas as peças recentemente suportadas. 2.2.7 usou Azduino3, 2.3.0+ usou Azduino4 e, começando com 2.6.0, usamos Azduino5 (embora não ofereça nenhum benefício para nós, além de economizar um quarto de GB de espaço em disco rígido e 40 MB de largura de banda de download se você instalar ambos megaTinyCore e DxCore através do gerenciador de placa.
A instalação manual é mais complicada - principalmente se você deseja suporte para a Série 2; consulte o guia de instalação para obter mais informações.
Um núcleo Arduino para o tinyAVR série 0, série 1 e agora série 2. Essas peças têm uma arquitetura aprimorada em comparação com as peças "clássicas" do tinyAVR (que são suportadas pelo ATTinyCore), com periféricos aprimorados e tempo de execução aprimorado para certas instruções (estes são semelhantes em ambos os aspectos do avançado AVR Dx-Series, bem como chips megaAVR série 0, como o ATmega4809 usado no Nano Every e Uno Wifi Rev. 2 oficial - embora a equipe do Arduino tenha feito o possível para dominá-los) em pacotes pequenos e de baixo custo típicos da linha ATtiny. Todas essas peças apresentam pelo menos um UART de hardware e uma interface SPI e TWI (nada daquele lixo USI como, por exemplo, o ATtiny85 possui), um sistema de eventos poderoso, lógica personalizada configurável, pelo menos um comparador analógico no chip , um oscilador interno surpreendentemente preciso e, no caso da Série 1, um canal de saída DAC real e, no caso da Série 2, um ADC diferencial sofisticado.
Além disso, as peças da série tinyAVR 0/1/2 são baratas - as peças de ponta, o 3226 e o 3227, com 32k de flash e 3k de SRAM (contra os 2k SRAM como o ATmega328p usado em Uno/Nano/ProMini) rodam pouco mais de US $ 1 em quantidade - menos do que muitas peças AVR ATtiny clássicas de 8k ("conjunto de instruções AVR, a um preço PIC"). Todas essas peças são classificadas para funcionar a 16 MHz ou 20 MHz (de 4,5 a 5,5 V) sem um cristal externo, e o oscilador interno é preciso o suficiente para comunicação UART.
Eles usam programação UPDI, não ISP tradicional como as peças clássicas do ATtiny faziam. Veja abaixo para mais informações. Obter um programador UPDI é simples - você pode usar um Arduino clássico baseado em 328p como programador usando jtag2updi - ou para melhores resultados com hardware mais barato, você pode usar qualquer adaptador serial USB e um resistor (e de preferência um diodo) usando o SerialUPDI incluído ferramenta, ou você pode usar AVRdude com um dos programadores Microchip (os programadores baseados em mEDBG/nEDBG/EDBG em sua placa de desenvolvimento, Atmel-ICE ou SNAP) ou qualquer ferramenta de programação UPDI que emule um desses (o que, até onde sei, todos eles fazem - se houver algum que o avrdude suporte e que meu núcleo não suporte, abra um problema para me avisar!).
Um bootloader serial, Optiboot_x (baseado na mesma base de código do bootloader Arduino Uno clássico, embora bastante alterado) é suportado nessas partes (o suporte à série 0/1 está atualmente ativo, a série 2 é esperada para a primeira semana de maio ; os ajustes para as novas peças são triviais), permitindo que sejam programadas através de uma porta serial tradicional. Consulte a seção Optiboot abaixo para obter mais informações sobre isso e as opções relevantes. A instalação do bootloader requer um programador UPDI. As placas de breakout montadas que vendo no Tindie estão disponíveis pré-bootloadadas (elas são inicializadas sob demanda). Dito isto, a experiência do usuário com o Optiboot é um pouco decepcionante nas peças da série 0/1, bem como nas peças da série 2 de 14 pinos, devido à falta de um pino de redefinição de hardware que possa ser usado com o circuito de reinicialização automática usual. para redefinir automaticamente no bootloader quando a porta serial for aberta. Você precisa desabilitar totalmente a programação UPDI (exigindo um programador HV se as configurações do fusível ou o bootloader precisarem ser alterados após o bootloading inicial) ou deixar o UPDI habilitado, mas iniciar qualquer upload dentro de 8 segundos após ligar a energia. As peças da série 2 de 20 e 24 pinos suportam um "pino de reinicialização alternativo", permitindo que funcionem mais como um Arduino tradicional.
A interface de programação UPDI é uma interface de fio único para programação (e depuração - Interface U niversal de Programação e Depuração ), que é usada no tinyAVR Série 0/1/2, bem como em todos os outros microcontroladores AVR modernos. . Embora sempre seja possível comprar um programador UPDI feito sob medida da Microchip, isso não é recomendado quando você estiver usando o IDE do Arduino em vez do IDE (terrivelmente complicado) da Microchip. Existem relatos generalizados de problemas no Linux para os programadores oficiais da Microchip. Existem duas abordagens alternativas de custo muito baixo para a criação de um programador UPDI, ambas com as quais a comunidade Arduino tem mais experiência do que os programadores oficiais.
Antes da existência do megaTinyCore, havia uma ferramenta chamada pyupdi - um programa Python simples para fazer upload para microcontroladores equipados com UPDI usando um adaptador serial modificado pela adição de um único resistor. Mas o pyupdi não era facilmente utilizável no IDE do Arduino e, portanto, essa não era uma opção. A partir da versão 2.2.0, megaTinyCore traz uma implementação Python portátil, que abre muitas portas; Originalmente estávamos planejando adaptar o pyupdi, mas a pedido de seu autor e de vários funcionários da Microchip, baseamos essa funcionalidade no pymcuprog, uma ferramenta "mais robusta" desenvolvida e "mantida pela Microchip" que inclui a mesma porta serial de upload recurso, apenas sem as otimizações de desempenho. Se estiver instalando manualmente, você deverá adicionar o pacote Python apropriado ao seu sistema operacional para usar este método de upload (uma instalação do sistema Python não é suficiente, nem é necessária).
Leia a documentação do SerialUPDI para obter informações sobre a fiação.
A partir da versão 2.3.2, com as melhorias dramáticas no desempenho e a confiabilidade comprovada do esquema de fiação usando um diodo em vez de um resistor, e à luz da instabilidade do firmware jtag2updi, este é agora o método de programação recomendado. A partir desta versão, a velocidade de programação foi aumentada em até um fator de 20 e agora excede em muito o que era possível com jtag2updi (a programação via jtag2updi é aproximadamente comparável em velocidade à programação via SerialUPDI na opção de velocidade "SLOW", 57600 baud; a versão normal de 230400 baud programa cerca de três vezes mais rápido que a versão SLOW ou jtag2updi, enquanto a opção "TURBO" (funciona em 460800 baud e aumenta a velocidade de upload em aproximadamente 50% em relação ao normal. A versão de velocidade TURBO só deve ser usada com dispositivos rodando a 4,5v ou mais, pois temos que rodar o clock UPDI mais rápido para acompanhar (também não é esperado). para ser compatível com todos os adaptadores seriais - esta é uma compensação intencional para melhorar o desempenho), mas permite o upload e a verificação de um esboço de 32kB em 4 segundos.
Três projetos estão sendo iterados: um adaptador serial de porta dupla onde ambas são portas seriais, um adaptador serial de porta dupla onde uma porta é sempre UPDI e uma porta única com um switch para selecionar o modo e uma placa adicional opcional para fornecer leds indicando status das linhas de controle do modem.
Eles permitirão o uso de um conector SMT JST-XH ou dupont - de qualquer forma com 6 pinos para serial (pinagem FTDI conforme marcado) e 3 pinos (para UPDI).
Todos os três serão capazes de fornecer 3,3 ou Vusb (nom. 5V), ou desconectar Vusb e 3V3 da energia, e esperar que o dispositivo alvo seja alimentado com 5,5V > Vdd > 1,8V. Os níveis lógicos utilizados neste caso serão a tensão de tudo o que for aplicado. Esteja avisado que em dispositivos seriais duplos, o barramento de alimentação VccIO é compartilhado! Ambos devem estar funcionando na mesma tensão, ser o mesmo dispositivo ou o adaptador deve estar configurado para alimentá-los e sua alimentação desconectada.
Dependendo do modelo do adaptador e do sistema operacional, descobriu-se que são necessárias diferentes configurações de tempo; no entanto, as configurações necessárias para evitar que até 230.400 baud falhem no Linux/Mac com a maioria dos adaptadores impõem uma penalidade de tempo muito maior no Windows, onde o manuseio serial do sistema operacional é lento o suficiente para que nada precise desse atraso...
O "atraso de gravação" mencionado aqui é para permitir que o comando apagar-gravar página termine de ser executado; isso leva um tempo diferente de zero. Dependendo do adaptador, a latência USB e o buffer implícito de 2 ou 3 bytes (é como um USART, e provavelmente implementado como um internamente. O terceiro byte que chega não tem para onde ir, porque o buffer de hardware tem apenas 2 bytes de profundidade) pode ser suficiente para permitir que funcione sem atraso explícito. Ou pode falhar no meio e relatar um "Erro com st". Quanto mais rápido for o tempo limite de latência do adaptador e mais rápido for o manuseio serial do sistema operacional, maior será a chance de isso ser um problema. Isso é controlado pelo parâmetro de linha de comando -wd
se o prog.py for executado manualmente. A partir da versão 2.5.6 esse atraso de gravação está mais próximo do tempo real solicitado (em ms), anteriormente ele tinha uma granularidade de vários ms, quando 1 é tudo que você precisava, e como resultado, a penalidade imposta foi brutal , principalmente em Windows.
Guia de seleção:
Adaptadores FTDI (FT232, FT2232 e FT4232 etc.), incluindo os falsos que estão disponíveis no eBay/AliExpress por cerca de US$ 2, no Windows o padrão é um período de latência terrivelmente longo de 16 ms. Mesmo com todos os esforços para limitar o número de períodos de atraso de latência que devemos esperar, isso prolongará um upload de 2,2 segundos para mais de 15 segundos. Você deve alterar isso para obter velocidades de upload toleráveis:
Um pode ser feito a partir de um clássico AVR Uno/Nano/Pro Mini; Nano clones baratos são a escolha usual, sendo baratos o suficiente para serem conectados e deixados assim. Não fornecemos mais documentação detalhada para esses processos; jtag2updi está obsoleto. Se você ainda estiver usando, você deve selecionar jtag2updi no menu ferramentas->programador. Esta era anteriormente nossa opção recomendada. Devido aos bugs persistentes do jtag2updi e à sua dependência da ferramenta 'avrdude', em grande parte não mantida (que, entre outras coisas, insere uma mensagem de erro espúria em todos os uploads UPDI feitos com ela), isso não é mais recomendado.
Aparentemente, o Arduino não está empacotando versões de 32 bits do avrdude mais recente. Eu defini uma nova definição de ferramenta que é uma cópia do arduino18 (o mais recente), exceto que ele usa a versão 17 no Linux de 32 bits, já que é o melhor disponível para essa plataforma. A versão arduino17 não suporta corretamente o upload com algumas das ferramentas de programação da Microchip.
Atualmente, isso é usado apenas nas últimas versões e deve corrigir o erro avrdude não disponível para esta plataforma.
Veja este documento cobrindo todos os AVRs modernos
Recurso | série 0 | Série 1 | 1+série | 2 séries |
---|---|---|---|---|
Clarão | 2k-16k | 2k-8k | 16k/32k | 4k-32k |
Número de pinos | 8-24 | 8-24 | 14-24 | 14-24 |
SRAM | 128b-1k | 128b-512b | 2k | 512b-3k |
CDT | Não | Sim | Sim | Não |
TCB | 1 | 1 | 2 | 2 |
ADC | 1x10 bits | 1x10 bits | 2x10 bits | 1x12 bits com PGA |
Pino VREF | Não | Não | Sim | Sim |
AC | 1 | 1 | 3 | 1 |
Evento * | 3 canais | 6 canais | 6 canais | 6 canais |
CCL** | doisLUTA | doisLUTA | doisLUTA | 4LUTA |
*
Os canais de eventos, exceto nos tinyAVRs da série 2 (e em todos os AVRs modernos não minúsculos), são subdivididos em dois tipos - síncronos (para o relógio do sistema) e assíncronos. Nem todos os geradores podem ser usados com um canal síncrono, e alguns usuários de eventos só podem usar canais síncronos, e as listas de canais são menos consistentes e mais . Essa loucura foi abandonada na primeira oportunidade – até o mega0 acabou com essa distinção.
**
apenas séries 2 e peças não pequenas podem disparar uma interrupção com base no estado CCL.
Todas as partes possuem entrada analógica disponível na maioria dos pinos (todos os pinos em PORTA e PORTB 0-1 e 4-5). O segundo ADC na série 1+ também pode usar os pinos do PORTC como entradas (consulte a referência analógica para obter informações sobre como usá-los).
Estas são as opções de orçamento. Embora sejam suportados, eles não são recomendados. Eles nunca recebem o "impulso" que o tinyAVR série 1 obtém em 16k, não têm segundo TCB em qualquer configuração, não têm TCD, apenas 3 canais de eventos, nenhum dos quais pode transportar saída de eventos RTC. Essas peças possuem 2 LUTs CCL como a série 1 e estão disponíveis com até 16k de flash em configurações de 14, 20 e 24 pinos (apenas 4k para peças de 8 pinos) e até 1k SRAM.
Eles têm 2k, 4k ou 8k de flash e 128, 256 ou 512b de memória RAM, assim como a série 0. Eles não possuem o segundo ADC, a configuração AC tripla ou o segundo TCB, embora possuam o TCD.
De repente, aos 16k, as peças da série 1 tornam-se muito mais interessantes. Acompanhando o flash maior está um arsenal de periféricos que parecem adequados para um chip muito maior, e sejam 16k ou 32k, todos eles recebem 2k de SRAM. Todo o segundo ADC é único entre os AVRs. Parece ter sido o campo de testes para muitos recursos que apareceram de forma refinada na série AVR Dx. O preço não parece levar em conta os periféricos muito superiores da série 16k 1,
Como você pode ver na tabela acima, a série 2 é quase mais um sidegrade do que uma atualização. Eles têm um ADC muito melhor, o sistema de eventos e CCLs são "normais", e têm mais RAM, a parte de 14 pinos está disponível com 32k de flash (um 3214 aparentemente foi planejado, mas depois cancelado; foi longe o suficiente para estar no ATPACK por um tempo antes de ser removido)
Escrevi um breve resumo de quando você gostaria de usar quais séries, se a escolha certa ainda não for óbvia.
Na definição oficial da placa Arduino para seu pacote de hardware "megaavr", eles implicam que a nova arquitetura nas peças da série 0 do megaAVR (que é quase a mesma usada no tinyAVR série 0 e série 1) é chamada de "megaavr " - esse não é um termo oficial. A Microchip usa o termo “megaAVR” para se referir a qualquer peça “ATmega”, seja ela de estilo antigo ou periféricos modernos. Não existem termos oficiais para se referir a todas as partes do AVR de uma família ou de outra, e um funcionário da Microchip até negou que existisse tal termo internamente. Não tenho certeza de como você pode fabricar dois conjuntos de peças, com as peças de cada conjunto tendo tanto em comum entre si e tão pouco em comum com o outro conjunto, sem que ninguém invente uma frase para se referir a qualquer um deles.
Neste documento, antes da versão 2.0.2, usamos a convenção do Arduino e, apesar de ter passado mais de um ano desde então, ainda continuo encontrando lugares onde os chamo de megaAVR. Por favor, relate isso usando um problema do github, se encontrar algum. Observe que os termos avr
e megaavr
ainda são usados internamente (por exemplo, em bibliotecas, para marcar com quais partes uma determinada biblioteca é compatível ou separar versões diferentes de um arquivo com base no que elas serão executadas). Isso continuará - temos que seguir isso para obter compatibilidade com o que a equipe do Arduino iniciou com o núcleo do Uno WiFi Rev. 2 e do Nano Every.
De qualquer forma, é necessária alguma palavra para se referir aos dois grupos e a Microchip não forneceu nenhuma. Na ausência de um termo oficial, tenho me referido aos dispositivos AVR anteriores a 2016 (com registros PORTx, DDRx, etc. para pinos) como " AVR clássico " e aqueles que o Arduino chama de megaavr como " AVR moderno ". Também existem algumas peças cujos módulos de E/S são muito mais parecidos com AVRs clássicos, mas que também possuem uma versão significativamente pior do conjunto de instruções e tamanhos de flash típicos de 1k ou menos. Eles usam a variante AVRrc (para núcleo reduzido) do AVR, enquanto a maioria dos AVRs clássicos usam AVRe ou AVRe+, e os AVRs modernos usam AVRxt. As partes AVRrc não são suportadas por este núcleo, e na infeliz ocasião em que eu precisar discutir essas partes profundamente decepcionantes, irei me referir a elas como partes " Reduced Core AVR ", já que esse é seu nome oficial, embora eu tenha muito conhecimento frases mais coloridas para eles. É recomendado que nenhum projeto use um AVR de núcleo reduzido , ponto final. Não que sejam obsoletos, são simplesmente péssimos. Recomenda-se que " AVRs modernos " (aqueles com os novos periféricos e conjunto de instruções AVRxt ) - série Ex, série Dx, tinyAVR 0/1/2 ou mega0 sejam usados para todos os novos designs
Folha de dados para o novo tinyAVR série 2 - Embora a folha de dados "cobre" apenas as peças de 16k, elas afirmam claramente que não há diferenças nos recursos entre peças com a mesma contagem de pinos (ou seja, não há peças "douradas" como o 16k/32k série 1), apenas entre peças com contagens de pinos diferentes e somente conforme ditado pela contagem de pinos (ou seja, um recurso na peça de 24 pinos estará na peça de 14 pinos, a menos que o de 14 pinos não tenha os pinos necessários e seja algo que não pode ser usado sem pinos). As peças de 14, 20 e 24 pinos estão todas listadas com flash de 4k, 8k, 16k e 32k; essas opções de tamanho de flash, respectivamente, vêm com 512, 1024, 2048 e 3072 bytes de SRAM (ou seja, as partes 4k e 8k têm o dobro da SRAM), as partes 4/8k recebem 128 bytes de EEPROM, as maiores recebem 256 Peças de 14 pinos vêm em SOIC e TSSOP, 20 pinos em SOIC (largo), SSOP e outros. QFN pequenino como o 1616 (desta vez eles nos deram a parte de 32k naquele pacote também, mas boa sorte em conseguir um, está em espera em todos os lugares - não consegui marcar nenhum) e 24 pinos no mesmo VQFN que o 3217.
TWI, SPI, USART0, AC0 permanecem inalterados, assim como NVMCTRL (as alterações necessárias no bootloader foram exclusivamente em relação ao suporte ao segundo USART). Opções de relógio inalteradas. TCB0 e TCB1 foram atualizados para a versão da série Dx: opção de evento de clock off, cascata e bits INTCTRL separados para OVF e CAPT - boas adições, mas nada relevante para o núcleo em si), e todas as partes possuem ambos TCBs. Agora temos 4 LUTs CCL e 2 sequenciadores, em vez de 2 e 1 - e eles podem disparar interrupções como outras partes do CCL (e diferentemente do tinyAVR série 0/1). Uma das características mais interessantes é que, como esperado, eles têm um segundo USART (aquele barulho que você ouve é o ATtiny841 e o ATtiny1634 soluçando no canto). Os registros PORTMUX agora são nomeados como o resto dos AVRs modernos - mas não perdemos o controle individual sobre os pinos de cada canal TCA WO. EVSYS agora funciona como em peças não-tinyAVR-0/1-Series (o que é uma mudança bem-vinda - a série 0/1 era a única, e algumas das maneiras pelas quais seu EVSYS era diferente eram uma droga ). Os recursos da Série 1 do TCD0, AC1/2, DAC0 e ADC1 desapareceram . Em seu lugar, o ADC0 é muito mais sofisticado e quase irreconhecível, o primeiro novo AVR lançado desde a aquisição que apresentava um verdadeiro diferencial ADC. (enfileirar outro lamento agonizante do pobre '841, que também tem um ADC incrivelmente sofisticado com ótimas opções de diferenciais, mas que parece completamente desatualizado perto dos novos)... a julgar pelo volume de postagens sobre diferentes tópicos que tenho parece, tenho a sensação de que o ADC diferencial não estava no topo da maioria de suas listas de desejos - mas estava no topo das listas dos principais clientes de chips, e é isso que estamos obtendo. E já era hora de conseguirmos um ADC diferencial adequado em vez daquele da série Dx. E é realmente muito chique. Veja abaixo.
megaTinyCore fornece uma implementação analogRead() e funções mais poderosas para usar oversampling e PGA (veja a seção de recursos analógicos abaixo).
Ah, e mais uma coisa... a configuração dos pinos UPDI tem as opções antigas - UPDI, I/O ou Reset... e uma nova: UPDI no PA0, com pino RESET de hardware no PB4! O Optiboot finalmente será uma opção viável e confortável pelo menos nas peças que possuem PB4, ou seja, não nas peças de 14 pinos. Que também é (se as vendas da minha loja Tindie servirem de indicação) o tipo mais popular.
Você acha que haverá 3 séries? Eu não. DD e os EA estão claramente perseguindo-os e assumindo posições estratégicas em torno do território tinyAVR. Acho que é apenas uma questão de tempo até que a marca seja eliminada, como fizeram com o megaAVR após o megaAVR série 0. Isso não é necessariamente uma coisa ruim: todas as peças das séries Dx e EA são muito semelhantes em mapeamentos de pinos e comportamento, o que é muito bom. Os minúsculos são menos sistemáticos, embora distribuam pinos para mais periféricos. O princípio orientador parece ter sido “nenhum periférico deixado para trás”. Compare com os mapeamentos de pinos das séries Dx e EA, onde tudo segue um plano mestre fixo. As peças têm ou não um determinado pino e, se não tiverem, não têm essa função disponível. Em ambos os grupos amplos, acho que há um gerente de produto cujo trabalho é atacar os engenheiros que pensam em fazer uma "exceção" à Pinagem Sagrada (uma vez que essas exceções inevitavelmente proliferam e são como terminamos com as atribuições de pinos do alvo de dardos com os olhos vendados no tinyAVR clássico)
A numeração dos pinos é estranha nos tinyAVRs, e a culpa é da Microchip - eles numeraram os pinos dentro das portas de maneira estranha: ele começa em ordem, exceto que PA0 é UPDI e geralmente não pode ser usado, então os pinos do PORTB são numerados na ordem inversa, então PORTC volta para a mesma numeração anti-horária de PORTA. Dá um tempo! Já que a tradição é usar o pino 0 para o primeiro pino, e fazer com que o último número seja o pino que você não pode usar sem colocar um fusível que dificulta a programação do chip. Eu preferiria poder numerá-los no sentido anti-horário, começando com A0, sem quebrar as convenções não escritas do código do Arduino. Pode-se argumentar que tomei uma decisão errada sobre os mapeamentos de pinos - talvez eles devessem ter começado com PA0 (inutilizável a menos que o fusível estivesse definido, caso em que o chip é difícil de programar) como pino 0 e depois numerado os pinos no sentido anti-horário. Mas você ainda não poderia fazer o tipo de truque que faria se todas as portas estivessem em ordem, a menos que numerasse os pinos PORTB ao contrário. Se você conseguisse se livrar da expectativa de que todos os pinos fossem numerados em ordem (e usasse apenas a notação PIN_Pxn), economias significativas poderiam ser obtidas
Eu prevejo que dentro de 2 a 4 anos haverá um AVR DA, DB, DD. Peças das séries DU (USB), EA e D/E/F com número de pinos de 8 (ou pelo menos 14) e peças de 64 pinos com flash de 128k e o novo ADC. E nada mais com a marca ATtiny. Possivelmente a maior questão que resta é se algum dia eles substituirão o ATmega2560 por um AVR moderno com 100 pinos no total (provavelmente 80-88 dos quais são E/S) e opções de flash de até 256k; Isso apresentaria três problemas - primeiro, após 56 pinos de E/S, não há mais registros VPORT - o espaço baixo de E/S está cheio com 28 VPORT e 4 GPIORs. Como eles lidarão com as 4 portas extras? (no 2560, elas eram apenas portas de segunda classe que eram acessadas mais lentamente e não tinham acesso de ciclo único. Tenho algumas reflexões sobre isso e a viabilidade de quão poucos opcodes estão disponíveis no apêndice A aqui. e segundo, para violar A barreira de 128K no Flash, você precisa ir a um balcão do programa de 17 bits. "D X parte em 256k de flash teria 32k de carneiro. Agora lembre -se de como o Progmem funciona no DX - eles não podiam ir até 32. 24K RAM é definitivamente possível, talvez até 28, mas a 32k, mais 32k para Flash mapeado, não deixa espaço para os SFRs, que estão no mesmo espaço de endereço.
Eu vendo placas de breakout com regulador, cabeçalho de atualização e cabeçalho em série na minha loja Tindie, bem como nas tábuas nuas. A compra da minha loja ajuda a apoiar um desenvolvimento adicional no núcleo e é uma ótima maneira de começar a usar essas novas peças emocionantes com o Arduino. Atualmente, as placas ATTINY1624 estão disponíveis, mas as peças de 20 e 24 pinos não serão vendidas como uma placa montada até que um design de PCB recém-revisado esteja de volta da casa do quadro para ativar o Autoreset no pino de retenção alt. Há também uma revisão da placa de 14 pinos - achada que é amplamente cosmética. A máscara de solda amarela precisa ir, pois a legibilidade parecia piorar nos últimos lotes. As novas placas também padronizam um espaçamento de 0,6 "entre as fileiras de pinos, em vez do espaçamento atual de 0,7", para que você poderá, por exemplo, colocar o cabeçalho do pino usinado neles e conectá-los a um soquete de amplo mergulho, ou Use -os com nossa placa de prototipagem otimizada para esse espaçamento de linha. Os quadros da série 0 montados estão sendo descontinuados e não serão reabastecidos quando eles se esgotarem. O mesmo acontecerá para as peças de 16k 2-Series assim que as 32k estiverem disponíveis.
O ADC na série 2 e EA-Series são os melhores ADCs que foram lançados em um AVR na era moderna do AVR. Além daqueles dois. As comparações mais próximas são os AVRs clássicos que obtiveram ADCs diferenciais com recursos de alto nível (o T841, Mega2560 e (surpreendentemente) o T861 sendo os concorrentes mais fortes). Embora não seja capaz do ganho insano de 100x e 200x que algumas partes se gabaram nos dias clássicos da AVR, nunca ficou claro para mim quanto do que estava sendo amplificado foi simplesmente ruído (considerando minha experiência reconhecidamente limitada tocar com ADCs diferenciais Vou dizer "provavelmente a maior parte, e definitivamente a maior parte, se você me deixar projetar o hardware, não conheço analógico!"). Esse novo ADC é certamente altamente capaz, com a verdadeira capacidade diferencial (ao contrário da série DA e DB), e uma que sobe de cabeça e ombros acima de qualquer coisa disponível em quaisquer outros AVRs modernos até o momento. O amplificador de ganho programável é uma nova capacidade, e resta ver que tipo de feitos de medição analógica as pessoas são capazes de sair dela; certamente parece promissor. Será especialmente interessante entender as diferenças entre usar o PGA com 1x ganho, vs não usando o PGA e os benefícios e desvantagens de fazê -lo. (O microchip seria bem servido por um documento que discutia como escolher a configuração correta do ADC para uma tarefa no caso geral; levantei essa preocupação com o microchip e a pessoa com quem falei indicou que era uma alta prioridade; enquanto A situação foi bastante aprimorada, ainda parece que o grupo DOC foi especificamente instruído a não fazer qualquer tipo de recomendação concreta real .
A adição de acumulação de 1024 amostras para fins de superamostragem e dizimação é uma adição bem-vinda, embora uma que também corra o risco de subestimar a magnitude e a relevância do erro de deslocamento. (Chegando 1024 amostras (todas com um determinado erro de deslocamento), depois dizimando a soma para produzir uma medição de ADC de 17 bits, facilita a imaginação de que qualquer erro seria confinado aos dois bits mais baixos. Mas se o erro Digamos que 5 LSB em uma única medição, quando você acumula 1024 amostras e dizime, você tem um erro de deslocamento de 160, é extremamente fácil ver isso e pensar que não é o sinal.
O primeiro chip em tamanho real (não pequeno) com o novo ADC está disponível em pacotes de 28 a 48 pinos com até 64k Flash. Havia a especulação usual sobre o que se algo mudaria de 2-Series para EA-Series: parece que a resposta é que um dos botões confusos foi removido e o corte automático de sinal para medições acumuladas (
O temporizador do tipo D é usado apenas para PWM nas peças da série 1 20/24 pinos 1 nas configurações de pino PWM padrão. Nas partes menores, não nos deixaria aumentar o número total de pinos PWM. Somente os pinos WOC e WOD (no PC0 e PC1, respectivamente), já não possuem PWM acionado por TCA. Como tal, como o analogwrite () não suporta nenhum recurso que seja ativado desligando o modo dividido (como PWM de 16 bits) ou aprimorado usando o timer tipo D (como ajustar a frequência), seria apenas pior, porque Seria necessário espaço adicional para armazenar a rotina para ligar e desligar o PWM de dois tipos de timer, em vez de um. Isso não é insignificante nas peças flash menores; É da ordem de 600 bytes. 150 para digitalWrite () e 450 para analogwrite () se forem chamados em um pino TCD PWM. O otimizador deve ser capaz de otimizar a parte dessas funções nesse caso, já que os pinos usados com essas funções não incluem pinos PWM TCD. Nota O otimizador os considerará independentemente, ou seja, o digitalWrite () incluirá o código para desativar o TCD PWM se for usado com um pino que usa TCD para PWM, se você chama ou não o analogWrite () nesse pino.
Ao contrário de quase todos os outros AVRs de todos os tempos (eu consigo pensar em talvez 3 exemplos, e apenas um deles é um "bônus" e não um "inaconado"), existem recursos adicionais de "bônus" baseados no tamanho do flash de peças dentro de uma família . As versões de 16k e 32k (somente) têm alguns recursos extras (que também não parecem ter sido considerados para preços) - todos eles têm 2k de RAM, sejam 16k ou 32k, eles têm 3 comparadores analógicos (incluindo um modo de janela opção), um segundo timer do tipo B do tipo B segundo - e o mais estranho de tudo o que eles têm um segundo ADC, diferindo apenas nos quais os canais correspondem!
Ao contrário dos AVRs clássicos, nessas partes, o flash é mapeado para o mesmo espaço de endereço do restante da memória . Isso significa que pgm_read_*_near()
não é necessário para ler diretamente do flash. Por esse motivo, o compilador coloca automaticamente qualquer variável declarada const
em progmem e acessá -la adequadamente - você não precisa mais declará -los explicitamente como progmem. Isso inclui literais de cordas citadas; portanto, a macro f () também não é mais necessária, embora para manter a compatibilidade com algumas bibliotecas de terceiros, f () ainda declara seu argumento progmem.
No entanto, observe que, se você declarar explicitamente uma variável progmem, ainda deverá usar as funções pgm_read
para lê -la, assim como nos AVRs clássicos. Quando uma variável é declarada progmem em peças com flash mapeado de memória, o ponteiro é deslocado (o endereço é relativo ao início do flash, e não no espaço de endereço); Esse mesmo deslocamento é aplicado ao usar as macros pgm_read_*_near()
. Observe que declarar as coisas progmem e acessar com pgm_read_*_near
, embora funcione bem, é mais lento e desperdiça uma pequena quantidade de flash (em comparação com simplesmente declarar as variáveis const); O mesmo vale para a macro f () com cordas constantes em 2.1.0 e posterior (por um período de tempo antes de 2.1.0, F()
não fez nada - mas isso causou problemas para bibliotecas de terceiros). Os autores sustentaram que o problema estava com o núcleo, não a biblioteca, e minha escolha era aceitar menos eficiência ou negar aos usuários acesso às bibliotecas populares). Usando a macro F()
pode ser necessária para a compatibilidade com algumas bibliotecas de terceiros (os casos específicos que forçaram o retorno de F()
sobre nós não eram desse tipo - realmente fomos capazes de fazer os que eu conhecia sobre o trabalho com o F ()-Código como Noo e eles ocuparam alguns bytes a menos flash como resultado).
As versões automotivas também devem funcionar. Você deve sempre selecionar as velocidades de relógio derivadas de 16 MHz nessas peças. Eles não suportam operação de 20 MHz e as opções de relógio sintonizadas não devem ser usadas.
Agora, na parte boa, onde conversamos sobre como tudo isso é exposto por Megatinycore. Começaremos com a questão de como você deve nos referir aos pinos para obter melhores resultados e, em seguida, avançar para os principais recursos, opções de menu, antes de terminar com uma série de links para documentos com mais detalhes em vários subsistemas.
A questão simples de como se referir a um pino para analogread () e DigitalRead (), particularmente em hardware não padrão, tem sido uma fonte persistente de confusão entre os usuários do Arduino. É minha opinião que grande parte da culpa repousa com as decisões tomadas pela equipe do Arduino (e autor de fiação diante deles) sobre como os pinos deveriam ser referidos; A designação de alguns pinos como "pinos analógicos" leva as pessoas a pensar que esses pinos não podem ser usados para operações digitais (elas são melhor pensadas como "pinos com entrada analógica" - como como existem "pinos que podem gerar PWM"). O fato de os pinos serem tradicionalmente renumerados confundiu ainda mais a água. Para peças clássicas não padrão do AVR, as questões geralmente são pioradas por múltiplos e incompatíveis "mapeamentos de pinos" criados por vários autores ao longo dos anos para tornar a parte agir "mais como um uno" ou para algum outro propósito (Attinycore é um particular Mess dessa maneira, com algumas partes com três mapeamentos de pinos totalmente diferentes, em pelo menos um caso, um dos mapeamentos alternativos é um trabalho de inspiração de diabo de puro mal, exigindo nada menos que uma tabela de pesquisa adicional para converter pinos analógicos em digital pinos).
Esse núcleo usa um esquema simples para atribuir os números de pinos Arduino: os pinos são numerados a partir do pino de E/S mais próximo do VCC como o pino 0 e prosseguindo no sentido anti-horário, pulando o pino Updi (principalmente) não utilizável. O pino Updi é então atribuído ao último número de pinos (como observado acima, é possível ler o pino Updi (trabalho analógico e digital), mesmo que não seja definido como GPIO). Recomendamos isso como último recurso: o pino Updi sempre possui seu pullup ativado quando não está definido como um pino GPIO e um sinal que se parece muito com a sequência de ativação da UPDI causará operação indesejada.
Para evitar toda a confusão sobre identidades de pinos e eliminar a ambiguidade, recomendamos o uso da notação pin_PXN para se referir a pinos, a menos que você esteja usando uma placa de desenvolvimento com números ou nomes diferentes para os pinos impressos. Isso maximizará a portabilidade do seu código para outro hardware semelhante e facilitará a consulta de informações sobre os pinos que você está usando nas folhas de dados relevantes, caso sejam necessárias.
Essa é a maneira recomendada de se referir aos pinos #defines
também é fornecida do formulário PIN_Pxn
, onde x
é a, b ou c e n
é um número 0-7 - (não deve ser confundido com o pin_an define descrito abaixo). Eles apenas resolvem o número de pinos digitais do pino em questão - eles não passam por um caminho de código diferente ou qualquer coisa. No entanto, eles têm utilidade específica ao escrever um código que funciona em toda a linha de produtos com periféricos vinculados a certos pinos (por porta), como a maioria dos periféricos. Várias partes do código de demonstração na documentação aproveitam isso. A manipulação direta da porta também é possível - e, de fato, várias opções adicionais poderosas estão disponíveis para ela - consulte a manipulação direta da porta .
PIN_Pxn
- não Pxn
, e não PIN_xn
- essas coisas significam coisas diferentes!
Quando um único número é usado para se referir a um pino - na documentação ou no seu código - é sempre o "número do pino Arduino". Estes são os números de pinos mostrados em laranja (para pinos capazes de analogread ()) e azul (para pinos que não estão) nos gráficos de pinagem. Todas as outras maneiras de se referir aos pinos são #decididas para o número de pinos Arduino correspondente.
O núcleo também fornece An
e PIN_An
(onde n
é um número de 0 a 11). Assim como no núcleo oficial, PIN_An
é definido como o número de pinos digitais do pino compartilhado com o canal analógico n, eles se referem aos números do canal ADC0. Esse sistema de nomenclatura é semelhante ao usado em muitos núcleos clássicos de AVR , mas aqui, eles são apenas #definidos como o número de pino Arduino correspondente . Se você precisar obter o número do canal analógico em um pino digital, use a macro digitalPinToAnalogInput(pin)
- mas você só precisará disso se estiver escrevendo uma biblioteca ADC avançada.
Essas peças (bem, pelo menos as séries 1/2-a série 0 foi para uma opção de orçamento, exceto que não diminuíram o orçamento e são apenas alguns centavos mais baratos) fornecem uma excelente caixa de ferramentas de versátil e periféricos poderosos; Os de ponta estão em pé de igualdade com ou melhor que as peças megaavr clássicas - por um preço do TinyAVR. Um dos princípios orientadores do design do Megatinycore, como nos meus outros núcleos, é permitir que as partes suportadas atinjam todo o seu potencial - ou o mais próximo possível das limitações do Arduino. Esta seção (muito grande) abrange os recursos dessas peças e como elas são expostas pelo Megatinycore, bem como as características do próprio núcleo. Esta seção (muito grande) tenta cobrir cada uma das áreas de características. Tente encontrar o recurso com o qual você está trabalhando se estiver tentando usar algum recurso de chip e ter problemas!
Não fazemos reivindicações sobre faixas de tensão ou temperatura para peças com overclock - tudo o que afirmamos é que pelo menos um dos chips que trabalhamos a essa velocidade à temperatura ambiente, executando um esboço específico, a 5V. Espera -se que sua milhagem varie, mas geralmente é melhor com uma especificação F versus uma peça de N ou U Spec.
IMPORTANTE - Leia sobre o ajuste antes de selecionar qualquer opção sintonizada!
Mais informações sobre essas velocidades de relógio podem ser encontradas na referência do relógio
As tensões mostradas são que são garantidas para funcionar pelas especificações do fabricante (a menos que empurre os limites da faixa de temperatura operacional, essas peças normalmente se saem muito melhor (as 2-Series geralmente funcionam a 32 MHz e 5V @ temperatura ambiente, mesmo a partir do oscilador interno; o 0 A série 1 também geralmente funcionará a 32 MHz com relógio externo, desde que a fonte de alimentação seja um estábulo 5.0-5.5V).
Nenhuma ação é necessária para definir o fusível OSCCFG
quando o esboço é carregado via UPDI. Quando carregado através do OptiBoot, o fusível não pode ser alterado; portanto, o que foi escolhido quando o carregador de inicialização foi queimado é o que é usado, e apenas "Burn Bootloader" ou o upload de um esboço via UPDI mudará isso.
Todas as opções de velocidade do relógio do oscilador interno usam a calibração padrão de fábrica, a menos que uma opção "sintonizada" seja selecionada; nesse caso, a calibração é ajustada conforme documentado na referência de ajuste . Isso pode ser usado para obter operação de 16 MHz em um chip OptiBoot fundido por 20 MHz e vice -versa.
Consulte Referência de Grade de Velocidade para obter mais informações sobre as notas de velocidade do fabricante. Observe que essas são as tensões e as velocidades do relógio nas quais é garantido que funcione. Essas peças devem ser adequadas para uso em aplicações, onde uma falha inesperada de alguma descrição pode representar um risco para pessoas ou propriedades (pense em carros, equipamentos industriais, aviões, reatores nucleares - lugares onde as pessoas poderiam morrer se a parte funcionasse) e eu Acredite também para aplicações militares, que têm requisitos de confiabilidade semelhantes, apenas pelo motivo oposto. Os usuários típicos de hobby ficarão muito mais relaxados com o potencial de problemas de estabilidade, com falhas sendo pouco mais que um incômodo e os extremos das partes estendidas da faixa de temperatura sendo muito além do que jamais precisaríamos. Supondo que a placa tivesse um revestimento à prova d'água, termicamente, uma parte n grau deve ser capaz de funcionar de acordo com o grau de velocidade em uma panela de água fervente. E isso é apenas o N-Spec. A especificação F deve ser boa para 125!
Foi estabelecido que as peças de temperatura estendida overclock melhor o que faz sentido. Espera -se que uma parte que seja especificada a 20 MHz a 125C tenha uma chance melhor de correr a 32 MHz à temperatura ambiente do que uma especificada apenas para correr a 20 MHz apenas a 105c
A partir da versão 2.4.0, agora fornecemos uma opção "placa de microchip oficial". Isso não faz nada de especial além de definir LED_BUILTIN
como o alfinete que tem o LED nessa placa, em vez de A7, e definindo um macro PIN_BUTTON_BUILTIN
definido como o pino com o botão do usuário e "fazer upload" com o não A versão -OptiBoot sempre usa o programador/depurador a bordo; Ferramentas -> O programador será usado apenas para "Burn Bootloader" e "Upload usando o programador". No caso do Nano de plataforma XPlained, ele também seleciona a versão do carregador de inicialização que usa os pinos alternativos para a porta serial - ele não usa automaticamente os pinos alternativos para o USART0 como se você tivesse feito serial.swap (1) ainda - A funcionalidade para suportar a troca padrão de pinos seriais virá em uma atualização futura, juntamente com outras alterações na maquinaria subjacente ao mecanismo PINSWAP, que esperançosamente reduzirá o uso do flash.
Como observado acima, eles podem não funcionar corretamente em plataformas Linux de 32 bits. Isso está além do meu controle; Não construo binários avrdude e também não estou assumindo essa tarefa. Eu já tenho muitos.
blink()
pega mais flash no xplained mini vs o xplained Pro?Ambos têm o mesmo Attiny817! Como eles podem ser diferentes?
Pelo mesmo motivo em que o piscar levará mais flash se você alterá -lo para usar PIN_PC0
em vez de PIN_PB4
: pc0, usado no mini xplained é um pino PWM, enquanto o PB4, usado pelo XPLER PRO não é. Como esse é o único alfinete em que o digitalWrite () está sendo usado, o compilador é livre para otimizar qualquer coisa que não seja necessária para o DigitalWrite () nesse pino, incluindo a funcionalidade para desativar a saída do PWM em um pino que suporta PWM . A diferença desaparece se o DigitalWrite () também é usado em um pino que suporta PWM nos dois dispositivos (resultando no resultado mais alto de uso do flash) ou se o digitalWrite () for substituído pelo DigitalWritefast (), o que usará menos flash (mas assume que você ganhou T chamá -lo em um pino que saindo PWM).
Sempre que um programador updi é usado para fazer upload de código, todos os fusíveis que podem ser definidos "com segurança" (como em, sem risco de bloquear a placa ou bloquear a placa se não tiver acesso a um programador de HV) e que tenha algum As opções de configuração internas serão definidas. Assim, exceto onde observado, o comportamento sempre corresponderá ao menu Ferramentas selecionadas. Em resumo, eles são tratados da seguinte maneira:
WDTCFG will not be changed - it is not configured by megaTinyCore except to reset it to the factory default when doing "burn bootloader".
BODCFG will not be changed - not safe, you could set the BOD level to 4.3 on a 3.3v system, and then it would need to get > 4.3v applied to reprogram it. If it is on the same circuit board as parts that would be damaged, this is a difficult situation to recover from.
OSCCFG will be set
TCD0CFG will not be changed - it is not configured by megaTinyCore except to reset it to the factory default when doing "burn bootloader".
SYSCFG0 will not be changed - not safe
SYSCFG1 will be set
APPEND will not be changed - it is not configured by megaTinyCore. There is insufficient demand to justify the development effort.to make use of this as DxCore does
BOOTEND will be set
LOCKBIT will not be changed - it is not configured by megaTinyCore; supporting the lockbits presents several additional complications, and commercial users with need of this facility are unlikely to be using the Arduino IDE to program production units.
BODCFG
não é seguro, porque definir isso como uma tensão mais alta do que a placa está em execução e ativando -a "tijolo" a placa até que uma tensão operacional mais alta possa ser fornecida; Isso pode ser particularmente estranho se for soldado no mesmo PCB que os dispositivos que não tolerarão essas tensões.
SYSCFG0
não é seguro, porque é aí que vive RSTPINCFG
; Alterar isso pode deixar a placa não agrícola, exceto por meio da programação de atualização de HV, e nem todos têm um programador de atualização de HV. No futuro, se/quando um programador que garante a capacidade de atualização do HV que pode ser selecionada como um programador (ou seja, torna -se possível fazer uma opção de ferramentas -> programador que funcionará apenas com programadores de HV), esse fusível será definido automaticamente ao usar aquele programador.
Como resultado em 2.2.0 e mais tarde, você não precisa mais 'queimar o carregador de inicialização' para alternar entre velocidades derivadas de 16 MHz e 20 MHz ao fazer o upload usando updi
Esse núcleo sempre usa a otimização do tempo de link para reduzir o uso do flash - todas as versões do compilador que suportam as peças Tinyavr 0/1/2 -Series também suportam LTO, portanto, não há necessidade de torná -lo opcional, como foi feito com Attinycore. Foi uma grande melhoria no código quando introduzida, normalmente da ordem de 5 a 20%!
Todas essas partes têm um grande número de entradas analógicas-DA e DB-Series têm até 22 entradas analógicas, enquanto a série DD tem entrada analógica em cada pino que não é usado para acionar o cristal de HF (embora os pinos no PORTC estejam Somente suportado quando o MVIO é desligado). Eles podem ser lidos com analogRead()
como em um AVR normal, e padrão para a resolução de 10 bits; Você pode alterar para os 12 bits completos com analogReadResolution()
e usar as funções analogread aprimoradas para fazer leituras automaticamente de amostragem e dizimada para obter uma resolução mais alta e fazer medições diferenciais. Existem 4 referências de tensão interna em 1.024, 2.048, 4.096 e 2.5V, mais suporte para tensão de referência externa (e VDD, é claro). As leituras do ADC são feitas 3 vezes mais rápidas que um AVR clássico, e essa velocidade pode ser dobrada novamente se o que você está medindo for baixa impedância ou estender o tempo de amostragem por um fator muito para ler fontes de impedância muito alta. Isso é detalhado na referência analógica.
As peças da série DX têm um DAC de 10 bits que pode gerar uma tensão analógica real (observe que isso fornece baixa corrente e só pode ser usado como referência de tensão ou tensão de controle, não pode ser usada para alimentar outros dispositivos). Isso gera tensões entre 0 e o VREF
selecionado (diferentemente da série 1 Tinyavr, isso pode ser VCC!). Defina a tensão de referência do DAC através da função DACR reference()
- Passe qualquer uma das opções de referência do ADC listadas na seção ADC acima (incluindo VDD!). Ligue para analogWrite()
no pino DAC (PD6) para definir a tensão a ser emitida pelo DAC (isso o usa no modo de 8 bits). Para desligar a saída DAC, ligue para digitalWrite()
ou turnOffPWM()
nesse pino.
Pode haver opções adicionais para configurar o DAC na série EA.
Veja a referência ADC e DAC para obter todos os detalhes.
Usando as constantes An
para pinos analógicos é descontinuado - a prática recomendada é apenas usar o número do pino digital ou, melhor ainda, usar a notação PIN_Pxn
ao chamar analogRead()
.
Existem mais opções do que no AVR clássico para redefinição, incluindo se o código for pendurado de alguma forma. O cronômetro de vigilância só pode redefinir (use o RTC e o poço para interrupções cronometradas).
Veja a referência Redefinir e Watchdog (WDT) e a biblioteca principal-atualizada Megatinycore
Esse núcleo adiciona vários novos recursos incluem E/S digital rápido (1-14 relógios, dependendo do que é conhecido no tempo de compilação e 2-28 bytes de flash (o número do pino deve ser conhecido no momento da compilação para as funções ________Fast()
e para definir todas as configurações por pino, o hardware possui com pinConfigure()
.
Veja a referência de E/S digital aprimorada .
Todas as peças da série 0/1 têm uma única porta serial de hardware (UART ou USART); As peças da Série 2 têm duas. Funciona exatamente como o das placas oficiais do Arduino, exceto que não há retirada automática, a menos que você o conecte fundindo o pino Updi como redefinição (exigindo hv-updi ou o optiboot bootloader para fazer upload de código) ou definido Up um "ersatz redefinir pino", conforme descrito em outras partes deste documento. Veja os gráficos de pinagem para os locais dos pinos seriais.
Antes de colocar a parte em um modo de suspensão ou desativar sua capacidade de transmitir, verifique se ele terminou de enviar os dados no buffer chamando Serial.flush()
, caso contrário, a porta serial emitirá caracteres corrompidos e/ou falhará para concluir a transmissão de uma mensagem.
Consulte a referência serial para obter uma lista completa de opções. A partir de 2.5.0, quase todo tipo de funcionalidade que o hardware serial pode fazer é suportado, incluindo modo RS485, Half-Duplex (via LBME e ODME) e até o modo SPI síncrono e Master, e 2.6.0 adicionará Autobaud, Mesmo que não seja muito útil.
Todas essas partes têm um único hardware SPI periférico. Funciona como o nas placas oficiais do Arduino usando a biblioteca SPI.H. Veja os gráficos de pinagem para a localização desses pinos. Em peças de 8 pinos, a única opção para o pino SS é PA0 (o pino Updi/Redefinir); Porém, isso não importa para os propósitos desse núcleo, porque, como a biblioteca oficial, isso apenas opera como um mestre, e o pino SS é usado apenas quando potencialmente age como escravo.
Em todas as peças, exceto as peças de 14 pinos, os pinos SPI podem ser movidos para um local alternativo (Nota: Em peças de 8 pinos, o pino SCK não pode ser movido). Isso é configurado usando os métodos SPI.swap()
ou SPI.pins()
. Ambos alcançam a mesma coisa, mas diferem na maneira como você especifica o conjunto de pinos para usar. Isso deve ser chamado antes de ligar para SPI.begin()
.
SPI.swap(1)
ou SPI.swap(0)
definirá o mapeamento para os pinos alternativos ( 1
) ou padrão ( 0
). Ele retornará verdadeiro se essa for uma opção válida e falsa se não for (você não precisar verificar isso, mas pode ser útil durante o desenvolvimento). Se uma opção inválida for especificada, ela será definida como padrão.
SPI.pins(MOSI pin, MISO pin, SCK pin, SS pin);
- Isso definirá o mapeamento para qualquer mapeamento que tenha os pinos especificados. Se essa não for uma opção de mapeamento válida, ele retornará false e definirá o mapeamento para o padrão. Isso usa mais flash do que SPI.swap()
para que o método seja preferido. O argumento SS pin
é opcional, pois o pino não é usado quando atua como um mestre da SPI, e nem esta biblioteca nem o suporte oficial da biblioteca Spi.H atuando como escravo.
Quando pode -se determinar que os argumentos passados para SPI.swap()
ou SPI.pins()
são inválidos no momento da compilação (mais comumente quando os argumentos são constantes, o que quase sempre são), o núcleo gera um compilação erro para esse efeito. Isso visa ajudar a impedir que esses problemas detectáveis exigem o tempo de depuração no hardware.
Esse núcleo desativa o pino SS, o que significa que o pino "SS" pode ser usado para qualquer final ciência do foguete ou qualquer coisa). Nos AVRs clássicos, se a SS fosse uma entrada e o SPI estivesse ativado, estava agindo como o pino SS e, se fosse baixo, trocaria o dispositivo para o modo escravo (e o spi.h não funcionaria até ficar de volta no mestre modo, que não foi feito automaticamente).
Todas essas partes possuem um único hardware I2C (TWI) periférico. Apresenta uma API compatível com a implementação padrão do Arduino, mas com suporte adicional para vários endereços de escravos, respondendo a endereços gerais de chamadas e - de maneira mais emocionante - operação de mestre e escravo simultânea! (Novo em 2.5.0).
Consulte Documentação Wire.H para obter uma descrição e detalhes completos. O hardware I2C é um dos periféricos mais complicados. A Wire teve muitos aprimoramentos quentes e quentes recentemente.
O núcleo fornece PWM de hardware através da função analogWrite()
padrão. Nas peças de 8 pinos (412, 212, 402, 204), 4 pinos PWM estão disponíveis. Em todas as outras peças, exceto peças de 1 série com 20 ou 24 pinos, 6 pinos PWM estão disponíveis, todos acionados pelo timer A (TCA0). As peças da série 1 de 20 e 24 pinos têm dois pinos adicionais, acionados pelo TCD0. A 2-Series aparentemente negociou o TCD0 por uma segunda porta serial e um ADC de super fundação-essas partes também têm 6 pinos PWM. Os temporizadores do tipo B (TCBN) não podem ser usados para pinos PWM adicionais - seus pinos de saída são os mesmos que estão disponíveis com o timer A e geralmente são úteis demais para justificar o uso de um TCB inteiro para. No entanto, você pode assumi -los se precisar gerar PWM em diferentes frequências, embora o fato de o pré -escaler não possa diferir do timer tipo A também limita esse uso. Consulte os gráficos de pinout para obter uma lista da qual os pinos suportam PWM.
A partir de 2.6.8, um submenu de ferramentas foi adicionado para permitir que você escolha entre os mapeamentos PWM plausivelmente úteis e (na série 1) para desativar o PWM TCD para salvar o flash.
Observe que o TCA0 (o timer do tipo A) em todas as partes é configurado pelo núcleo na inicialização para operar no modo dividido, a fim de suportar o maior número de pinos de PWM possível com analogWrite()
. A partir das versões 2.2.x, foi adicionada uma função takeOverTCA0()
, que pode ser chamada para instruir o núcleo não gravar para os registros TCA0 nem assumir qualquer modo ou comportamento específico para o TCA0. analogWrite()
não gera PWM, exceto em pinos acionados pelo TCD0 nas peças de 20/24 pinos, nem digitalWrite()
o desativarão se você quiser reconfigurar o TCA0 para outros fins, consulte o guia abaixo e "Redefinição dura" o temporizador de volta à configuração do estoque.
Os 3216, 1616, 816, 416 e os 3217, 1617 e 817 têm dois pinos PWM adicionais acionados pelo timer d (PC0 e PC1 - pinos 10 e 11 em x16, 12 e 13 em x17). O timer D é um temporizador assíncrono (Async), e as saídas não podem ser ativadas ou desativadas sem interromper brevemente o timer. This results in a brief glitch on the other PWM pin (if it is currently outputting PWM) and doing so requires slightly longer - though the duration of this glitch is under 1 us. If TCD is used as the millis timer - which is the default on any part that has a type D timer (in order to keep the timers that are more readily repurposed available - TCD0 is not an easy peripheral to work with), this will result in millis()
losing a very small amount of time (under 1 us) every time PWM is turned on or off on a TCD pin.
As of 2.2.0, analogWrite()
of 0 or 255 on a TCD-driven PWM pin does not disconnect the pin from the timer - instead it results in a constant HIGH
or LOW
output without disconnecting the timer (use digitalWrite()
for that ). This means that analogWrite(PIN_PC0, 0)
or analogWrite(PIN_PC1, 0)
can be used to connect the timer to the pin without outputting PWM (yet) - doing this on both pins prior to setting any other duty cycles would allow one to ensure that no glitch of any sort occurs on the other TCD0 pin when the second pin is connected to it. Only digitalWrite()
or turnOffPWM()
will disconnect the timer from the pin . When outputting a HIGH
in this way, the pin is "inverted"; this means that digitalRead()
on it will return 0, not 1 (if you're digitalRead()
'ing a pin, which you have set to output a constant HIGH
, using analogWrite()
, and it's one of those two pins, it will read LOW
. However, if you are using digitalRead()
on a pin that you've set to output a constant value, you may be doing something wrong in general.
Because TCD is async, and can run from the unprescaled internal oscillator, that means you can lower the system clock frequency without affecting the speed of the PWM. While there is a difference in PWM frequency between 16-MHz derived and 20-MHz derived clocks, there is no change in frequency for different system clock speeds for the TCD-controlled pins (the TCA-controlled pins will vary by a factor of two) The exception to this is when TCD0 is used as the millis/micros timing source at 1 MHz - running at full speed there resulted in spending an unreasonable fraction of runtime in the millis()
ISR (tens of percent of the time).
TCD0 is used for millis()
/ micros()
by default on parts that have it. Be aware that this does have a small flash penalty, so you can save flash by switching to use TCA or a TCB as the timer. That will also make micros()
return faster. There is a shortage of timers on most of these parts, and I have not seen anyone talking about or posting code that reconfigures the TCD. Meanwhile everyone seems to be reconfiguring the TCA and many libraries need a TCB. These factors have been the impetus for making TCD0 the default for millis()
/ micros()
: it is least likely to directly interfere.
On some versions of megaTinyCore prior to 2.2.0, PWM on the TCD0 pins was entirely broken.
For general information on the available timers and how they are used PWM and other functions, consult the guide: This also covers the PWM frequencies that these timers will give you at various system clocks. Timers and megaTinyCore
Support for tone()
is provided on all parts using TCB0, unless TCB1 is present and TCB0 is set as millis()
source. This is like the standard tone()
function. Unlike on some classic AVRs, it does not support use of the hardware 'output compare' to generate tones; due to the very limited PWM capabilities and restricted prescaler selection for the TCB timers, this is not practical. See caveats below if using TCB0 or TCB1 for millis()
/ micros()
settings. See the timer reference for more information
tone()
can only play a tone on one pin at a time. In theory you can play one tone per Type B timer, simultaneously, without anything more exotic than what tone()
does now other than adding a capability to manage the multiple pins. It is my opinion that those belong in a library, not the core. See comments in tone.cpp
for some thoughts if you want to implement something like that - I'd be happy to give more thoughts if you have questions.
megaTinyCore provides the option to use any available timer on a part for the millis()
/ micros()
timekeeping, controlled by a Tools submenu. It can be disabled entirely if needed to save flash, allow use of all timer interrupts or eliminate the periodic background interrupt. By default, TCD0 will be used by on parts that have one - otherwise TCA0 will be used (in versions prior to 1.1.9, TCA0 was used by default on parts that could output PWM with TCD0 on pins not available for TCA0 PWM). All timers available on the parts can be used: TCA0, TCD0 (on parts that have it), TCB0, TCB1 (where present) and the RTC. Many of these - particularly the non-default options, involve tradeoffs. In brief, TCA0 is a very versatile timer that users often want to reconfigure, TCD0 loses a small amount of time when PWM is turned on or off on the two TCD0 PWM pins (10,11 on 20-pin parts, 12,13 on 24-pin parts), TCB0 conflicts with Servo
and tone()
on parts that don't have TCB1, and when the RTC is used micros()
is not available at all because the clock isn't fast enough. With these limitations in mind, the timer selection menu provides a way to move millis()
/ micros()
to the timer most appropriate for your needs.
For more information, on the hardware timers of the supported parts, and how they are used by megaTinyCore's built-in functionality, see the Timers and megaTinyCore Reference .
2.3.0 fixed a long-standing (though surprisingly low impact) "time travel" bug.
millis()
If the RTC is selected as the timer for millis()
timekeeping, micros()
will not be available. Additionally, this timer will be configured to run while in STANDBY sleep mode. This has two important consequences: First, it will keep time while in sleep. Secondly, every 64 seconds, the RTC overflow interrupt will fire, waking the chip - thus, if you are using the RTC for millis()
and putting the part into sleep, you should declare a volatile global variable that you set in the ISR that is supposed to wake the part, eg volatile boolean ShouldWakeUp=0;
, set it to 1 in the ISR, and when you put the ATtiny to sleep, have it check this immediately after waking, going back to sleep if it's not set, and clearing it if it is set, eg:
void GoToSleep () {
do {
sleep_cpu ();
} while (!ShouldWakeUp)
ShouldWakeUp= 0 ;
}
This functionality will be made easier to use via ModernSleep when that library is available.
This board package also supports using an external 32.768khz crystal as the clock source for the RTC (not supported on 0-Series or 8-pin parts - not our fault, the hardware doesn't support it). If this is used, make sure that the crystal is connected between the TOSC1 and TOSC2 pins (these are the same as the TX and RX pins with the default pin mapping - very convenient right?), that nothing else is, that no excessively long wires or traces are connected to these pins, and that appropriate loading capacitors per crystal manufacturer datasheet are connected (and that it's not a full moon - I found the 32k crystal to be extremely uncooperative. To reduce power usage, they try to drive the crystal as weakly as they can get away with, which in turn makes it more susceptible to interference.
Yes, you can use an external oscillator for the RTC, at least on 1 and 2 series parts. When it's an oscillator not a crystal, it can be fed to either TOSC0 or EXTCLK; better support for this will come in the future. Note that while TOSC0 won't let you run the RTC at widlly faster speeds. EXTCLK will.
printf()
Support for "printable" Class Unlike the official board packages, but like many third party board packages, megaTinyCore includes the printf()
method for the printable class (used for UART serial ports and most everything else with print()
methods); this works like sprintf()
, except that it outputs to the device in question; por exemplo:
Serial.printf( " Milliseconds since start: %ld n " , millis());
Note that using this method will pull in just as much bloat as sprintf()
and is subject to the same limitations as printf - by default, floating point values aren't printed. You can use this with all serial ports You can choose to have a full printf()
implementation from a Tools submenu if you want to print floating point numbers, at a cost of some additional flash.
printf()
and Variants Thereof Have Many Pitfalls There are a considerable number of ways to screw up with printf()
. Some of the recent issues that have come up:
printf()
- printf()
bugs are a common cause of software bugs in the real world. Be aware that while you can use F() on the format string, there are no warnings for invalid format strings in that case ; a conservative programmer would first make the app work without F() around the format string, and only switch to F() once the format string was known working.From cplusplus.com:
The length sub-specifier modifies the length of the data type. This is a chart showing the types used to interpret the corresponding arguments with and without length specifier
(if a different type is used, the proper type promotion or conversion is performed, if allowed): Strikethrough mine 'cause that don't work here (and it's not my fault nor under my control - it's supplied with avrlibc, and I suspect that it's because the overhead of implementing it on an 8-bit AVR is too large). When incorrect length specifiers are given (including none when one should be used) surprising things happen. It looks to me like all the arguments get smushed together into a group of bytes. Then it reads the format string, and when it gets to a format specifier for an N byte datatype, it grabs N bytes from the argument array, formats them and prints them to whatever you're printing to, proceeding until the end of the format corda. Thus, failing to match the format specifiers' length modifiers with the arguments will result in printing wrong data, for that substitution and all subsequent ones in that call toprintf()
.
The table below comprises the relevant lines from that table - many standard types are not a thing in Arduino (their original was several times longer, but including that mess would just complicate this discussion.
comprimento | di | uox X | f F e E g G a A | c | é | p | n |
---|---|---|---|---|---|---|---|
(nenhum) | int16 | uint16 | flutuador | interno | char* | vazio* | int* |
ah | int8 | uint8 | char* | ||||
eu | int32 | uint32 | int32_t* |
Notice that there is no line for 64 bit types in the table above; these are not supported (support for 64-bit types is pretty spotty, which is not surprising. Variables of that size are hard to work with on an 8-bit microcontroller with just 32 working registers), and using uint64's is something you should try to avoid, similar to driving on the wrong side of the road, flying kites during thunder storms, or drinking bleach. While all have been suggested (Europe is really persistent about the side of the road; As far as I'm concerned, it comes down to physics; mirror image symmetry i. This applies to all versions of printf()
- the capability is not supplied by avr-libc.
There are reports of memory corruption with printf, I suspect it is misunderstanding of above that is actually at hand here.
printf()
Implementation A Tools submenu lets you choose from three levels of printf()
: full printf()
with all features, the default one that drops float support to save 1k of flash, and the minimal one drops almost everything and for another 450 bytes flash saving (will be a big deal on the 16k and 8k parts. Less so on 128k ones). Note that selecting any non-default option here will cause it to be included in the binary even if it's never called - and if it's never called, it normally wouldn't be included. So an empty sketch will take more space with minimal printf()
selected than with the default, while a sketch that uses printf()
will take less space with minimal printf()
vs default.
Então:
Menu selection | printf() or similar used? | Sobrecarga |
---|---|---|
Padrão | Não | 0 by definition |
Padrão | Sim | apx 1500 |
Mínimo | Não | apx 1000 |
Mínimo | Sim | apx 1100 |
Completo | Não | apx 2800 |
Completo | Sim | apx 3000 |
Notice how when not using printf or similar functions, you are far better off leaving it on the default, as opposed to switching to minimal thinking you'll save flash, because you you'll use more flash not less.
All pins can be used with attachInterrupt()
and detachInterrupt()
, on RISING
, FALLING
, CHANGE
, or LOW
. All pins can wake the chip from sleep on CHANGE
or LOW
. Pins marked as Async Interrupt pins on the megaTinyCore pinout charts (pins 2 and 6 within each port) can be used to wake from sleep on RISING
and FALLING
edges as well. Those pins are termed "fully asynchronous pins" in the datasheet.
Advanced users can instead set up interrupts manually, ignoring attachInterrupt()
, manipulating the relevant port registers appropriately and defining the ISR with the ISR()
macro - this will produce smaller code (using less flash and RAM) and the ISRs will run faster as they don't have to check whether an interrupt is enabled for every pin on the port.
For full information and example, see the Interrupt Reference.
Like my other cores, Sketch -> Export compiled binary will generate an assembly listing in the sketch folder. A memory map is also created. The formatting of the memory map leaves something to be desired, and I've written a crude script to try to improve it, see the Export reference for more information. see Exported Files documentation
The EESAVE fuse can be controlled via the Tools -> Save EEPROM menu. If this is set to "EEPROM retained", when the board is erased during programming, the EEPROM will not be erased. If this is set to "EEPROM not retained", uploading a new sketch will clear out the EEPROM memory. Note that this only applies when programming via UPDI - programming through the bootloader never touches the EEPROM.
You must do "burn bootloader" in order to apply changes after modifying this setting, as EESAVE is on the same fuse as one the one that can be used to disable UPDI, making it an "unsafe" fuse (one that if written with the wrong options, can make the device difficult to reprogram). We don't write "unsafe" fuses like that when uploading sketches, because it should never be possible to brick your board just by uploading, which you can do without opening the tools menu and seeing that you forgot to change the options back to the intended ones for the current project.
These parts officially support BOD trigger levels of 1.8V, 2.6V, and 4.2V, with Disabled, Active, and Sampled operation options for when the chip is in ACTIVE and SLEEP modes - Disabled uses no extra power, Active uses the most, and Sampled is in the middle. As of 2.1.0, the ACTIVE/SLEEP modes have been combined into a single menu, the nonsensical options (such as using more aggressive BOD while sleeping than while awake) were removed, and the previously unexposed options were added. Sampled mode is now available with two sample rates (the faster one uses ever so slightly more power, as you would expect) and "Enabled hold wake": in that mode, BOD is disabled in sleep, enabled when not sleeping, and when waking up, code execution does not begin until the BOD is ready. See the datasheet for details on power consumption and the meaning of these options.
You must do Burn Bootloader to apply this setting. This fuse is considered "unsafe" as you can set the BOD level to a voltage higher than the highest voltage tolerated by other chips soldered to the same pcb and sharing a power rail with the AVR, and this will then prevent reprogramming without desoldering things (because you'll either be unable to program the AVR because it's in brownout reset, or if you power it at a high enough voltage to leave BOR, you would damage the afore-mentioned low voltage parts).
Between the initial header file and preliminary datasheet release, and the more recent versions of each, several BOD settings were removed from the tinyAVR 0/1-Series datasheets, and the atpack release notes described them as "unqualified" - (I understand that this has something to do with the factory testing process and possibly the vetting process for the safety critical applications these parts are certified for. ). The three official BOD levels are the voltages that the chip is guaranteed (Yup, they use that word in the datasheet!) to work at, within the manufacturer specified temperature range and running at a system clock frequency no higher than specified at that voltage. Nevertheless, the other 5 BOD levels are believed to work as one would expect (I have used them successfully), but Microchip does not provide any guarantee that they'll work, even if all other operating requirements are met, and I do not believe they are tested in production. These "not guaranteed" voltages are still supported by the megaTinyCore BOD dropdown menu, but (as of 2.0.4 - the first version that has the new headers) are marked as "(Unofficial)" in the submenu. Note that the new headers no longer provide the *_gc
enum entries for these BOD level.
| BOD level
0/1-series| BOD level
2-series | Guaranteed speed
Temperatura normal. range | Guaranteed speed
Elevated temp. range) |-----------|------------------|------------------| | 1.8V | 1.8V | 5 MHz | 4 MHz | | 2.1V | 2.15V | unofficial | unofficial | | 2.6V | 2.6V | 10 MHz | 8 MHz | | 2.9V | 2.95V | unofficial | unofficial | | 3.3V | 3.3V | unofficial | unofficial | | 3.7V | 3.7V | unofficial | unofficial | | 4.0V | 4.0V | unofficial | unofficial | | 4.2V | 4.3V | 20 MHz | 16 MHz |
Normal temperature range is -40-105C on 0/1-series parts and -40-85C on 2-series parts. These parts have a letter N (0/1-series) or U (2-series) at the end of the part number; this is marked on the physical chip as well on 0/1-series, but not on 2-series.
Extended temperature range is -40-125C, and these parts are denoted with the F temperature spec. The extended temperature range column applies when the temperature range is above the normal range and below 125C on F-spec parts. The normal temperature range column still applies to F-spec parts if they are running in the normal temperature range.
Most existing Arduino libraries work. See the Supported Libraries List for a more complete list and discussion of what kinds of libraries might have issues. Of the few libraries that don't work, a handful happened to also be extremely popular and heavily used, such that it was felt necessary to include a compatible version with megaTinyCore. In addition to these, libraries which expose hardware that is only present on the modern AVRs, are also included. These libraries are listed below.
This library supplies two functions to check tuning status of the chip it's running on, and now adds two software reset functions (via WDT or via software reset). It also holds the massive keywords.txt file that highlights register names and core-specific functions.
megaTinyCore helper library docs
The usual NeoPixel (WS2812) libraries, including the popular FastLED as well as AdafruitNeoPixel, have problems on these parts - they depend on hand-tuned assembly, but the execution time of several key instructions has been improved. The improvements enable significant simplification of the code for driving these LEDs. This core includes a compatible version of the tinyNeoPixel library for interfacing with these ubiquitous addressable LEDs. There are two versions, both tightly based on the Adafruit_NeoPixel library. One implements a truly identical API, differing only in name (and obviously the fact that it works on tinyAVR and Dx-Series and megaAVR 0-Series parts at clock speeds from 8 MHz to 48 MHz, instead of on most classic AVRs at 8, 12, and 16 MHz). The other version makes a slight change to the constructor and drops support for changing length at runtime, in order to realize significant flash savings (around 1k). See the tinyNeoPixel documentation and included examples for more information.
The standard EEPROM.h is available here - it works like it does on any AVR. USERSIG.h
(from "User Signature" which the datasheet has sometimes called the USERROW
) it has the same API as EEPROM, though there may be future additions to harmonize with Dx-friendly functions for updating multiple bytes. The Dx-Series parts can only erase the whole USERROW, so potentially each byte written could involve erasing and rewriting it all - the question of how to deal with that is why DxCore doesn't have a USERSIG library yet). The name "USERSIG" refers to the alternate name of the USERROW, the "User Signature" space - the name USERROW could not be used because it is defined by the io headers (it's the struct
of type USERROW_t
, made up of USERROW.USERROW0
through USERROW.USERROW31
. Not the most useful thing, but we never override the io header file definitions unless working around a bug.
Note: Prior to 2.1.0, we tried to get clever with supporting the USERROW
through the EEPROM library; that not only was shortsighted (as it's logically inconsistent on anything with more than 256b of EEPROM), it also introduced some serious bugs. Use the USERSIG.h
library for that instead.
The usual Servo library from library manager is incompatible with these parts (minor changes could make it "work", but with glaring issues and a dependence on the configuration of TCA0). This core provides a version of the Servo library which will select an appropriate timer (TCB0 is the only option on most parts, on parts with a TCB1 (2-Series and 3216, 3217, 1617, 1616 and 1614), TCB1 will be used instead, provided it's not being used for millis()
). Except on parts with a TCB1, Tone cannot be used at the same time as the Servo library. Servo output is better at higher clock speed; when using servos, it is recommended to run at the highest frequency permitted by the operating voltage, to minimize jitter.
Warning If you have installed a version of the Servo library to your /libraries folder (including via library manager), the IDE will use that version of the library (which is not compatible with these parts) instead of the one supplied with megaTinyCore (which é). As a workaround, a duplicate of the Servo library is included with a different name - to use it, just #include
instead of #include
- no other code changes are necessary.
Note that the Servo libraries were only fixed in version 2.2.0 - prior to that we had a Servo library, but it didn't work due to an astonishingly large number of bugs (I swear I tested it - apparently not well enough).
Written by @MCUDude, this provides a more accessible (much more accessible!) wrapper around the optiboot.h library (which was written by the famous @westfw) . This supports writing to the flash of any device using Optiboot, by having the application code call routines in the bootloader to write to the flash. All modern AVRs have built-in flash protection mechanisms that permit only code executing from the bootloader section ( BOOTCODE
, in their terminology) to write to the application section ( APPCODE
). While the hardware does support a third flash section ( APPDATA
) which can be written by code running in APPCODE
this is only usable if there is also a BOOTCODE
section defined (otherwise the entire flash is treated as BOOTCODE
which can never be self-programmed), and would require a separate implementation of this library to use. It would also be possible to get flash-write-from-app without use of an actual bootloader through an analog of the trick used by the DxCore Flash.h for this. Since there appears to be little demand for such a thing, that functionality is not currently implemented (they were implemented on DxCore's flash writing library because the additional effort was virtually nil, and because there was a user with a particular interest in that feature). If someone wants this, and will adapt the library, I can add the entry point to the core and give you little chunks of inline assembly that will call it. Note on terminology: on AVR Dx-Series, the fuses are called BOOTSIZE
and CODESIZE
whereas on 0/1-Series tinyAVRs they're called BOOTEND
and APPEND
. I'm not quite sure how they didn't foresee customer confusion when they called the "APPlication END" that... Regardless of the names they do the same thing, although the granularity on tinyAVRs is finer, as you would expect.
Optiboot_flasher documentation
Warning As noted above, there is a library for DxCore that is also named Flash.h
. Both allow an application to write to the flash using Optiboot if present. That is the only similarity they have . The API, NVM hardware, method used to call the bootloader, and basically everything about these libraries is different . Be sure you write code for the one that matches the hardware you're using. While I (Spence Konde) wrote the DxCore one, I don't have a particularly strong opinion about which way is "right". We made them independently, but not because we each thought the other one's idea of how it should be done was wrong. They largely reflect the way the hardware interacts with its flash. For example, the one for megaTinyCore is page-oriented with its own page buffer, and these parts write in a page-oriented manner, while the DxCore library only cares about pages when erasing - on those parts, the flash is written with word or even byte granularity!
All of these parts have at least a pair of Configurable Custom Logic (CCL) blocks; official Microchip terminology calls them "LUTs" in reference to the LookUp Table (aka truth table). We use the term "logic block" instead, to avoid confusion with other kinds of lookup table (the "lookup table" in a logic block is very different from most lookup tables; containing 8 entries, each of which is a 0 or a 1, it is a single byte, which isn't much of a table), and to prevent users who missed this paragraph from being confused by the terminology. Each block allows you to supply an arbitrary 3-input truth table, as well as configuring additional options like a synchronizer, filter, or edge detector. The CCL operates asynchronously (unless you using the synchronizer) - meaning that things can happen faster than the clock speed. Thesynchronizer that will synchronize the CCL output to one of several clock sources (probably the system clock will be what you would synchronize with). The inputs can come from pins, events, or other peripherals. There's a feedback input as well, which allows a great many exciting possibilities, and a "sequencer" that can act like a latch or flip-flop using the outputs of a pair of logic blocks as its inputs. This is an incredibly powerful peripheral - especially on the 2-Series parts, which have a second pair of logic blocks, as well as the capability to trigger an interrupt when the state of one changes.
The Logic ( #include Logic.h
) library provides a simple wrapper around the CCL hardware in the tinyAVR 0/1/2-Series devices. This library is also included in DxCore and MegaCoreX, covering all AVRs with CCL hardware. Written by @MCUDude.
Logic library documentation
These parts have either 1 (everything else) or 3 (1614, 1616, 1617, 3216, and 3217) on-chip analog comparators which can be used to compare two analog voltages, and, depending on which is larger, do one or more of the following: generate an event output, control an output pin, or fire an interrupt. One of the voltages can be the internal reference (0-Series) or an internal reference scaled by an 8-bit DAC (everything else). This library, written by @MCUDude, provides a simple wrapper around the analog comparator(s) which makes their configuration easier and resulting code more readable (also easier on the wrists - less stuff to type in all caps) than manually configuring registers, while exposing nearly the full featureset of the analog comparators on these parts. Do note does not support the Window Comparator option for the parts with 3 comparators; There doesn't exactly seem to be a lot of demand for that one, though!
The Comparator library ( #include Comparator.h
) is also included in DxCore and MegaCoreX, covering all modern AVRs with comparator hardware. Written by @MCUDude.
Comparator library documentation
In general you should expect the following about library compatibility:
__AVR_ARCH__ >= 102
.architectures=*
would suggest that it would work anywhere - all this means is that there are not separate folders with implementations for different architectures. It does not mean that the library does not make assumptions about architecture, test against architecture specific stuff with #ifdef
s and so on. Unfortunately, library authors often use this when they know it works with a couple of architectures, shrug their shoulders and assume it'll work anywhere and put down a * in that field.The amount of effort required to port a given library will vary widely depending on the library. Some are straightforward for anyone reasonably familiar with these parts and what to generally expect and approach it. Any library associated with some peripheral that both classic and modern had, it's probably going to be a straightforward change if you just need to swap out the classic peripheral for the modern one - Yes, every bitfield will be named differently, but only rarely did a modern AVR's peripheral lack a feature the classic version had. The USART on classic AVR has whack stuff like MPCM, and the 9 bit mode - sorry, modes. Even the layout of some of the registers is similar - the parts aren't as different as they appear at first. Another type is the "bitbanger", where they're using direct port writes; the solution to this is cookbook - switch to using the relevant PORT or VPORT registers. Input capture is a little more complicated because you have to set up the event channel, and figure out how to offer that in a library (that is the hard part). But the consistent factor is that generally, none of these things are long slow painful slogs. And as noted above, many libraries will work out of the box, or have already been adapted.
The fact that many libraries can be ported no or little underlines the need for reports from users about incompatible libraries as well as compatible ones not listed on the table linked below. Usually reports of non-working libraries to add to the table result in the library getting fixed , and the fixed library being added to the table; Almost all of the fruit here low hanging. So when you come upon incompatible libraries report it to me! Many libraries that were initially incompatible were fixed up in under 10 minutes. Porting typical libraries from classic AVRs requires a fraction of the effort that the "tar pit" libraries included with this core take to port to new modern AVR families (these are Comparator, Logic, Event: Logic and Event are both, on their own, large, complicated, "system-like" peripherals. The CCL is just complex in general, and has seen relatively modest changest between families, except for the t0/1. Event is simple in theory and much more complicated in practice, in no small part because the implementation on the 0-series, 1-series, mega0, 2-series/DA/DB/DD, EA and the EB are each different. And a single library has to support all of them with a consistent interface and paper over all the differences.
I know lots of people use libraries that aren't on that list, and I fully expect that there is a great number of libraries that work and are not listed, and I'd love to hear about them. Use the "discussions" or email me, or even submit a PR to add a line to the table. I want to hear about working libraries so others will know they work and not hesitate, and I'm even more interested in ones that don't work so they can be fixed - or determined to be unfixable)
For more information on resetting from software, using the Watchdog Timer, the causes of unexpected resets and how to prevent them, and generally all things reset-related, see the Reset Guide.
It is often useful to identify what options are selected on the menus from within the sketch; this is particularly useful for verifying that you have selected the options you wrote the sketch for when opened later by yourself or someone who you shared it with. Or, you can use such in-sketch identification, combined with preprocessor #if
macros, to select the appropriate code depending on the part or options at hand.
There are a great number of #define
s provided to get information about the hardware in-use, in order to write portable and flexible code in your sketch or, especially, library code.
Note : You cannot distinguish an extended temperature range part from a normal one from software. For 0/1-series, most packages mark the temperature grade. this is no longer true on the 2-series, nor on any part released after the 1-series - So better make sure you mark those parts if you unpack them, because the only alternative is to give the lot number to Microchip support, and they'll tell you if it's an F, a U, or an N (FUN letters - but notice that you can't turn any letter into any other letter without both erasing and adding lines. The same is true of the different set of letters they used on automotive parts - BMZ or something - less FUN, but they had the same "modification resistance" (hey, on at least one occasion, a quantity of t13'd had the markings polished off and were remarked as tiny85's and sold as such on aliexpress and ebay - that was worth doing to some criminal in China! Unethical behavior is of course the norm for companies everywhere, but in the US, criminality of the company (as opposed to rogue employees) is not pervasive. When it rises above that, low end of chinese industry - ex, virtually all PVC wire is 2-8 AWG smaller than what is printed on the wire; same with silicone wire (but FEP insulated wire is always spot on, cause it's not at the low end ya see), one has to assume that (well, if they still marked the parts) someone has taken a bunch of parts marked I (vertical line), added 3 horizontal lines to each one (One imagines, with the same sort of automated chip marking method that would be used for putting any other pattern, except here it would just be the missing parts of an E. The consistency of the location of markings on packages is remarkably consistent specimen to specimen, such that you might be able to target by position and get it close enough to be convincing, and with just 3 small marks and no grinding, and significant price difference between I and E spec parts for certain parts (oddly, not for most tinies). Of course when they adopted the I and E when they stopped marking parts at all, so this is academic. But can you seriously imagine anyone inspecting 200 boards and writing down every lot number he saw, and emailing the list to Microchip and asking for confirmation that they're all E's as he ordered?).
A new version of Optiboot (Optiboot_x) now runs on the tinyAVR 0-Series, 1-Series and 2-Series chips. It's under 512 bytes, and works on all parts supported by this core, allowing for a convenient workflow with the same serial connections used for both uploading code and debugging (like a normal Arduino Pro Mini). Note the exception about not having autoreset unless you disable UPDI (except for the 20 and 24-pin 2-Series parts which can put reset on PB4 instead), which is a bit of a bummer.
To use the serial bootloader, select a board definition with (optiboot) after it. Note - the optiboot suffix might be visually cut off due to the width of the menu; the second / lower set of board definitions in the board menu are the optiboot ones). The 2-Series Optiboot definitions and the 0/1-Series Optiboot definitions are separate entries in the board menu.
See the Optiboot referencefor more information.
These guides cover subsystems of the core in much greater detail (some of it extraneous or excessive).
Covering top-level functions and macros that are non-standard, or are standard but poorly documented, and which aren't covered anywhere else.
The API reference for the analog-related functionality that is included in this core beyond the standard Arduino API.
The API reference for the digital I/O-related functionality that is included in this core, beyond the standard Arduino API, as well as a few digital I/O-related features that exist in the hardware which we provide no wrapper around.
Documents the (largely intended for internal use) dirty inline assembly macros that are used by the core to improve performance or reduce code size.
Includes a list of all interrupt vectors that can be used, how the flags are cleared (not a substitute for the datasheet - just a very quick reminder), which parts each vector exists on, and and what parts of the core, if any, make use of a vector. It also has general guidance and warnings relating to interrupts their handling, including estimates of real-world interrupt response times.
The USARTs (Serial) have some greatly enhanced functionality compared to the stock core.
Serial UPDI is our recommended tool for UPDI programming.
Supported clock sources and considerations for the use thereof.
Manufacturer specs for speed at various voltages, and some discussion of BOD thresholds - this is written largely from a very conservative perspective, in contrast to most of the documentation.
These are provided by the core and can be overridden with code to run in the event of certain conditions, or at certain times in the startup process.
The core feature #define
s are used by megaTinyCore and other cores I maintain as well. This also documents what constant values are defined by the core for version identification, testing for features, and dealing with compatibility problems.
Export compiled binary generates both assembly listings and memory maps, in addition to the hex file. The options selected are encoded in the name of the file to help prevent confusion and make it easy to compare two configurations when you are surprised by the differences between them. Also provides links to a script I wrote to reformate memory maps so you can read the damned things.
The sources of reset, and how to handle reset cause flags to ensure clean resets and proper functioning in adverse events. Must read for production systems
The installation and operation of the Optiboot bootloader (for uploading over straight serial (not SerialUPDI)) is described here. Not recommended except on the 20/24-pin 2-Series (since they have the alt reset pin) or for special use cases that demand it.
This contains detailed information on how the timers are used in megaTinyCore, and some background on their capabilities.
These guides are older; some are still relevant.
This has been recently updated and will likely be turned into a Ref_TCA0.
This document describes how (on the 0 and 1 Series only) the ADC can be taken over and reconfigured, with particular attention to free running mode. The 2-Series ADC is different, and it would require changes to reflect those differences.
A delightful, though unfortunately short, document on bare metal programming in C.
The bible of the AVR instruction set. Like any such tome, it is a lengthy document which contains timeless wisdom from the creator(s), written in obtuse and challenging language and a confusing syntax (though you won't go to hell if you don't read it, if you're writing assembly without it, you might not be able to tell the difference).
As promised, a bunch of additional information was released; Unfortunately it leaves some of the key questions unanswered.
printf()
implementation - The default option can be swapped for a lighter weight version that omits most functionality to save a tiny amount of flash, or for a full implementation (which allows printing floats with it) at the cost of about 1k extra flash. Note that if non-default options are selected, the implementation is always included in the binary, and will take space even if not called. This applies everywhere that format strings are used, including Serial.printf()
.attachPortAEnable()
and replace A
with the letter of the port) before attaching the interrupt. This allows attachInterrupt()
to be used without precluding any use of a manually defined interrupt (which is always much faster to respond). Basically any time you "attach" an interrupt, the performance is much worse.millis()
, micros()
and pulseInLong()
will be available. If set to disable, these will not be available, Serial methods which take a timeout as an argument will not have an accurate timeout (though the actual time will be proportional to the timeout supplied); delay()
will still work. Disabling millis()
and micros()
saves flash, and eliminates the millis()
interrupt every 1-2 ms; this is especially useful on the 8-pin parts which are extremely limited in flash. Depending on the part, options to force millis()
/ micros()
onto specific timers are available. A #error
will be shown upon compile if a specific timer is chosen but that timer does not exist on the part in question (as the 0-Series parts have fewer timers, but run from the same variant). If RTC is selected, micros()
and pulseInLong()
will not be available - only millis()
will be.There are however a few cautions warranted regarding megaTinyCore - either areas where the core is different from official cores, or where the behavior is the same, but not as well known.
If you are manually manipulating registers controlling a peripheral, except as specifically noted in relevant reference pages, the stated behavior of API functions can no longer be assured. It may work like you hope, it may not, and it is not a bug if it does not, and you should not assume that calling said API functions will not adversely impact the rest of your application. For example, if you "take over" TCA0, you should not expect that using analogWrite()
- except on the two pins on the 20/24-pin parts controlled by TCD0 - will work for generating PWM. If you reconfigure TCA0 except as noted in Ref_Timers, without calling takeOverTCA0
, both analogWrite()
and digitalWrite()
on a PWM pin may disrupt your changed configuration.
While we generally make an effort to emulate the official Arduino core, there are a few cases where the decision was made to have different behavior to avoid compromising the overall functionality; the official core is disappointing on many levels. The following is a (hopefully nearly complete) list of these cases.
Earlier versions of megaTinyCore, and possibly very early versions of DxCore enabled the internal pullup resistors on the I2C pins. This is no longer done automatically - they are not strong enough to meet the I2C specifications, and it is preferable for it to fail consistently without external ones than to work under simple conditions with the internal ones, yet fail under more demanding ones (more devices, longer wires, etc). However, as a testing aid, we supply Wire. usePullups()
to turn on the weak internal pullups. If usePullups()
ever fixes anything, you should install external pullups straight away. Our position is that whenever external pullups are not present, I2C is not expected to work. Remember that many modules include their own on-board pullups. For more information, including on the appropriate values for pullups, see the Wire library documentation
The official core for the (similar) megaAVR 0-Series parts, which megaTinyCore was based on, fiddles with the interrupt priority (bet you didn't know that!) in methods that are of dubious wisdoom. megaTinyCore does not do this, saving several hundred bytes of flash in the process, and fixing at least one serious bug which could result in the microcontroller hanging if Serial was used in ways that everyone tells you not to use it, but which frequently work anyway . Writing to Serial when its buffer is full, or calling Serial.flush()
with interrupts disabled, or during another ISR (which you really shouldn't do ) will behave as it does on classic AVRs and simply block, manually calling the transmit handlers, until there is space in the buffer for all of the data waiting to be written or the buffer is empty (for flush()
). On th stock megaAVR core, this could hang forever.
This is deprecated on the official core and is, and always has been, a dreadful misfeature. Dropped as of 2.3.0.
digitalRead()
Does Not Turn Off PWM On official cores, and most third party ones, the digitalRead()
function turns off PWM when called on a pin. This behavior is not documented by the Arduino reference. This interferes with certain optimizations, makes digitalRead()
take at least twice as long (likely much longer) as it needs to and generally makes little sense. Why should a "read" operation change the thing it's called on? We have a function that alters the pin it's called on: digitalWrite()
. There does not seem to be a logically coherent reason for this and, insofar as Arduino is supposed to be an educational platform it makes simple demonstrations of what PWM is non-trivial (imagine setting a pin to output PWM, and then looking at the output by repeatedly reading the pin).
digitalWrite()
and INPUT
Pins Like the official "megaavr" core, calling digitalWrite()
on a pin currently set INPUT
will enable or disable the pullups as appropriate. digitalWrite()
also supports "CHANGE" as an option; on the official core, this will turn the pullup on, regardless of which state the pin was previously in, instead of toggling the state of it. The state of the pullup is now set to match the value that the port output register was just set to.
This was done because of the huge volume of code that makes use of this behavior. We experimented with making pinMode() do the inverse for INPUT and INPUT_PULLUP, but this was removed by unanimous agreement by everyone in the discussion thread.
analogWrite()
and TCD0 Pins Please see the above PWM feature description if using PWM on those pins and also using digitalRead()
or direct port writes on the same pins (PIN_PC0, and PIN_PC1).
On the official "megaavr" board package, TCA0 is configured for "single mode" as a three-channel 16-bit timer (used to output 8-bit PWM). megaTinyCore always configures it for "Split mode" to get additional PWM outputs. See the datasheets for more information on the capabilities of TCA0. See Taking over TCA0 for information on reconfiguring it. One downside to this is that the compare channels do not support buffering, so changing the duty cycle can cause a glitch lasting up to one PWM cycle (generally under 1 ms).
0 is a count, so at 255, there are 256 steps, and 255 of those will generate PWM output - but since Arduino defines 0 as always off and 255 as always on, there are only 254 possible values that it will use. The result of this is that (I don't remember which) either analogWrite(pin,254)
results in it being LOW
2/256's of the time, or analogWrite(pin,1)
results in it being HIGH
2/256's of the tempo. On megaTinyCore, with 255 steps, 254 of which generate PWM, the hardware is configured to match the API, and this does not occur. As it happens, 255 also (mathematically) works out such that integer math gets exact results for millis()
timing with both 16-MHz-derived and 20-MHz-derived clock speeds, which is relevant when TCA0 is used for millis()
tempo. The same thing is done for TCD0, though to 509, giving 510 steps. analogWrite()
accounts for this, so that we can get the same output frequency while keeping the fastest synchronization prescaler for fastest synchronization between TCD0 and system clock domains.
On the official "megaavr" board package, as well as DxCore, the Type B timers are used to generate 8-bit PWM (one pin per timer). There are very few circumstances where this could increase the number of usable PWM pins. These timers are just too scarce and valuable on these parts. Being minimally useful for PWM, in short supply, and highly desirable for other purposes, support for using Type B timers for PWM was removed in order to save space that would otherwise be used initializing these timers for PWM and handling them in analogWrite()
et . al. If a Type B timer is used for millis()
, it is configured in a radically different way than the official core does it.
They return and expect uint8_t
(byte) values, not enum
s like the official megaavr board package does. Like classic AVR cores, constants like LOW
, HIGH
, etc are simply #define
d to appropriate values. The use of enum
s unfortunately broke many common Arduino programming idioms and existing code (granted, these idioms were poor programming practice - they're also incredibly widespread and convenient), increased flash usage, lowered performance and made optimization more challenging. The enum
implementation made language design purists comfortable and provided error checking for newbies, because you couldn't pass anything that wasn't a PinState to a digital I/O function and would see that error if you accidentally got careless. Nevertheless, due to all the complaints, a compatibility layer was added to the official core, so all the old tricks would work again, it was just less performant. However, that got rid of what was probably the most compelling benefit by allowing the workarounds: the fact that it did generate an error for new users to train them away from common Arduino practices like passing 1 or 0 to digitalWrite()
, if(digitalRead(pin))
and the like. The choice of names of the enum
s also had the perverse effect of making PinMode(pin,OUTPUT)
(an obvious typo of pinMode(pin,OUTPUT)
) into valid syntax (comma operator turns pin,OUTPUT
into OUTPUT
, and it returns a new PinMode
of value OUTPUT
...) and does nothing with it, instead of a syntax error (It took me over an hour to find the erroneous capitalization. That evening, I converted the digital I/O functions to the old signatures and removed the enum
s). Anyway - the enum
s are not present here, and they never will be; this is the case with MegaCoreX and DxCore as well.
There are two classes of significant low level architectural differences (aside from the vastly improved peripherals): the improved instruction set and the unified memory address space.
The classic AVR devices all use the venerable AVRe
(ATtiny) or AVRe+
(ATmega) instruction set ( AVRe+
differs from AVRe
in that it has hardware multiplication and supports devices with more than 64k of flash). Modern AVR devices (with the exception of ones with minuscule flash and memory, such as the ATtiny10, which use the reduced core AVRrc
) all use the latest iteration of the AVR instruction set, AVRxt
. AVRxt
has much in common with AVRxm
(used in XMega parts) in terms of instruction timing - and in the few places where they differ, AVRxt
is faster (SBIC, as well as LDD, and LD with pre-decrement, are all 1 clock slower on AVRxm
vs AVRxt
or AVRe
), however AVRxt
doesn't have the single-instruction-two-clock read-and-write instructions for memory access LAT
, LAC
, LAS
, and XCH
. The difference between subspecies of the AVR instruction set is unimportant for 99.9% of users - but if you happen to be working with hand-tuned assembly (or are using a library that does so, and are wondering why the timing is messed up), the changes are:
As you can see, everything that involves writing to the SRAM is faster now; it would appear that any time it is writing to a location based on one of the pointer registers or the stack pointer, it's a single cycle. All the other improvements except CBI
and SBI
can be viewed as a consequence of that. Of course, the variants of CALL
are faster; they have to put the return address into the stack. I can't say I've ever felt like LAT
, LAC
, or LAS
would be terribly useful as they are described in the instruction set manual - those take a register and the address pointed to by the Z register, load the contents of the specified address and toggle, set or clear in that memory address the bits that were set to begin with in the register. If that worked on special function registers, it would be a very useful instruction, taking PERIPHERAL.REGISTER |= SOME_BIT_bm;
from a 5 clock, non-atomic operation to a 2 clock atomic one! But it says they only work on SRAM... so not as much of a loss. XCH
is more obviously useful than the others, but all 4 of them come with the need to set up the Z register... which in many cases would take long enough that it wouldn't be a notable improvement.
Note that the improvement to PUSH
can make interrupts respond significantly faster (since they have to push the contents of registers onto the stack at the beginning of the ISR), though the corresponding POP
s at the end aren't any faster. The change with ST
impacted tinyNeoPixel. Prior to my realizing this, the library worked on SK6812 LEDs (which happened to be what I tested with) at 16/20 MHz, but not real WS2812's. However, once I discovered this, I was able to leverage it to use a single tinyNeoPixel library instead of a different one for each port like was needed with ATTinyCore (for 8 MHz, they need to use the single cycle OUT
on classic AVRs to meet timing requirements, the two cycle ST
was just too slow; hence the port had to be known at compile time, or there must be one copy of the routine for each port, an extravagance that the ATtiny parts cannot afford. But with single cycle ST
, that issue vanished).
Oh, and one other instruction it doesn't have that (some) AVRxm parts have: The hardware DES
encryption instruction - an instruction which is most effective at marking AVRxm as, ah, back from the time when DES
was a big deal.
On all modern AVRs with up to 48k of flash, both the flash and ram reside in the same address space - On tinyAVRs, the program memory starts at 0x8000, while on megaAVR 0-Series, it starts at 0x4000 to leave room for the 48k of flash that they can have, and on the Dx-Series parts with up to 32k of flash, they have the same layout as the tinyAVRs, while Dx-Series parts with 64k or 128k of flash have a 32k section of flash mapped at any given time (how to make sure variables go into this memory mapped flash has been described elsewhere in this document). There is another big and fundamental change to the layout of the address space as well: the registers are organized by peripheral. PORTA is assigned 0x400 to 0x41F. PORTB is the next 32 bytes, and so on - and the address space is far sparser - all the peripherals have multiple "reserved" registers that may or may not get functions added in the future. And each instance of a peripheral on a part that has multiple of them has the same layout. You can, say, pass a pointer to a TCB around without the functions that get it knowing which TCB they'll get, and then access the TCB registers through it. On classic AVRs the names of the registers were consistent, but their locations were all over the place, packed much more tightly, so that sort of trick isn't possible. This also means that the EEPROM (and USERROW) are part of this unified address space (on classic AVRs, reading was accomplished through special function registers, and was far more awkward).
The lowest 64 registers are special - you can read or write them with the IN
or OUT
instructions (hence, "I/O space") in a single clock cycle, without setting up a pointer to them as you would need to with ST
or LD
. The 32 "Low I/O registers" additionally have bit-level access instructions CBI
and SBI
to clear and set bits, and SBIC
/ SBIS
to skip the next instruction if a certain bit is set or cleared. On all AVRxt parts released so far, the low I/O registers are used only for the VPORTs, up to VPORTG or the last port on the part, whichever comes first. This means VPORTG.OUT |= 1 << n
, where n is known at compile-time and constant , is a 1 clock cycle atomic operation , while VPORTG.OUT = 1 << n
(note the =
in lieu of |=
) takes two clock cycles. For the latter, the first cycle is to put the value to be stored into a register, and the second is to write it with an OUT
instruction. The GPIOR0-3 registers occupying the last 4 bytes in the low I/O space (those are user-defined registers to use as you choose. We use GPIOR0 internally during startup to record reset cause, and store two types of warnings applicable to tuning ). The reset flag register is always cleared very early in startup to prevent dirty resets, and when using a bootloader, so that it can honor bootloader entry conditions on next reset). No other part of this core touches those registers, and we only set GPIOR0; we never read it. So all can be used freely, as long as you remember that GPIOR0 is not empty when you enter setup, and contains the reset cause flags. Other Low I/O registers are not used by the hardware.
The 32 "high I/O registers" are used even less - they only contain the the stack pointer, RAMPZ
on the 128k DA/DB parts, SREG
, and CCP
(Configuration Change Protection - where _PROTECTED_WRITE()
does it's magic to let you write to protected registers. That's all - 5 out of 32 registers are used, the rest are "reserved". On classic AVRs, registers for assorted peripherals that the designers thought would be accessed often were put into the I/O space, so it was a disappointment that they didn't put an alias of any other registers there. I'd vote for the intflags registers to be aliased there
megaTinyCore itself is released under the LGPL 2.1. It may be used, modified, and distributed freely, and it may be used as part of an application which, itself, is not open source (though any modifications to these libraries must be released under the LGPL as well). Unlike LGPLv3, if this is used in a commercial product, you are not required to provide means for users to update it.
The DxCore hardware package (and by extension this repository) contains DxCore as well as libraries, bootloaders, and tools. These are released under the same license, unless specified otherwise . For example, tinyNeoPixel and tinyNeoPixel_Static, being based on Adafruit's library, are released under GPLv3, as described in the LICENSE.md in those subfolders and within the body of the library files themselves.
The pyupdi-style serial uploader in megaavr/tools is a substantially renovated version of pymcuprog from Microchip, which is not open source has now been released under the open source MIT license! .
Any third party tools or libraries installed on behalf of megaTinyCoreCore when installed via board manager (including but not limited to, for example, avr-gcc and avrdude) are covered by different licenses as described in their respective license files.