mirror of
https://github.com/elua/elua.git
synced 2025-01-08 20:56:17 +08:00
Merge branch 'master' into lm3s_usb_cdc
This commit is contained in:
commit
f9eec264db
2
.gitignore
vendored
2
.gitignore
vendored
@ -17,4 +17,4 @@ doc/dist
|
||||
doc/cache
|
||||
*~
|
||||
*.*~
|
||||
|
||||
luac.cross*
|
||||
|
@ -457,7 +457,6 @@ builder:set_exe_extension( ".elf" )
|
||||
-- Create the ROM file system
|
||||
make_romfs()
|
||||
-- Creaate executable targets
|
||||
builder:make_depends( source_files )
|
||||
odeps = builder:create_compile_targets( source_files )
|
||||
exetarget = builder:link_target( output, odeps )
|
||||
-- This is also the default target
|
||||
|
@ -17,9 +17,9 @@ local components =
|
||||
arch_platform = { "ll", "pio", "spi", "uart", "timers", "pwm", "cpu", "eth", "adc", "i2c", "can" },
|
||||
refman_gen = { "bit", "pd", "cpu", "pack", "adc", "term", "pio", "uart", "spi", "tmr", "pwm", "net", "can", "rpc", "elua", "i2c" },
|
||||
refman_ps_lm3s = { "disp" },
|
||||
refman_ps_str9 = { "pio", "rtc" },
|
||||
refman_ps_str9 = { "pio" },
|
||||
refman_ps_mbed = { "pio" },
|
||||
refman_ps_mizar32 = { "disp" },
|
||||
refman_ps_mizar32 = { "lcd" },
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -23,34 +23,56 @@ data_en =
|
||||
ret = "1 if the ADC interface exists, 0 otherwise"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_op#( unsigned id, int op, u32 data );",
|
||||
desc = "Executes an operation on an ADC channel",
|
||||
args =
|
||||
{ sig = "u32 #platform_adc_get_maxval#( unsigned id );",
|
||||
desc = "Gets the maximum conversion value the channel may supply (based on channel resolution)",
|
||||
args = "$id$ - ADC channel ID",
|
||||
ret = "the maximum possible conversion value"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_set_smoothing#( unsigned id, u32 length );",
|
||||
desc = "Sets the length of the moving average smoothing filter",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID",
|
||||
[[$op$ - the operation that must be executed. It can take any value from @#adc_operations@this enum@, as follows:
|
||||
<ul>
|
||||
<li>$PLATFORM_ADC_GET_MAXVAL$: get the maximum conversion value the channel may supply (based on channel resolution)</li>
|
||||
<li>$PLATFORM_ADC_SET_SMOOTHING$: sets the length of the moving average smoothing filter to $data$ </li>
|
||||
<li>$PLATFORM_ADC_SET_BLOCKING$: sets whether or not sample requests should block, waiting for additional samples</li>
|
||||
<li>$PLATFORM_ADC_IS_DONE$: checks whether sampling has completed</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_TIMER$: selects a timer to control sampling frequency</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_CLOCK$: set the frequency of sample acquisition</li>
|
||||
</ul>]],
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_SET_SMOOTHING$, specifies the length of the moving average filter (must be a power of 2). If it is 1, filter is disabled.",
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_SET_BLOCKING$, specifies whether or not sample requests block. If 1, requests will block until enough samples are available or sampling has ended. If 0, requests will return immediately with up to the number of samples requested.",
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_OP_SET_TIMER$, specifies the timer to use to control sampling frequency.",
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_OP_SET_CLOCK$, specifies the frequency of sample collection in Hz (number of samples per second). If 0, timer is not used and samples are acquired as quickly as possible."
|
||||
"$length$ - the length of the moving average filter (must be a power of 2). If it is 1, the filter is disabled.",
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"the maximum possible conversion value when $op$ == $PLATFORM_ADC_GET_MAXVAL$",
|
||||
"whether or not sampling has completed (1: yes, 0: no) when $op$ == $PLATFORM_ADC_IS_DONE$. This will return 1 (yes), if no samples have been requested.",
|
||||
"the actual frequency of acquisition that will be used when $op$ == $PLATFORM_ADC_OP_SET_CLOCK$",
|
||||
"irellevant for other operations"
|
||||
}
|
||||
ret = "$PLATFORM_OK$ if the operation succeeded, $PLATFORM_ERR$ otherwise."
|
||||
},
|
||||
|
||||
|
||||
{ sig = "void #platform_adc_set_blocking#( unsigned id, u32 mode );",
|
||||
desc = "Sets whether or not sample requests should block, waiting for additional samples",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID",
|
||||
"$mode$ - specifies whether or not sample requests block. If 1, requests will block until enough samples are available or sampling has ended. If 0, requests will return immediately with up to the number of samples requested.",
|
||||
},
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_is_done#( unsigned id );",
|
||||
desc = "Checks whether sampling has completed",
|
||||
args = "$id$ - ADC channel ID",
|
||||
ret = "1 if sampling has completed, 0 if not",
|
||||
},
|
||||
|
||||
{ sig = "void #platform_adc_set_timer#( unsigned id, u32 timer );",
|
||||
desc = "Selects a timer to control the sampling frequency",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID",
|
||||
"$timer$ - the ID of the timer to use to control the sampling frequency.",
|
||||
},
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_set_clock#( unsigned id, u32 freq );",
|
||||
desc = "Set the frequency of sample acquisition",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID",
|
||||
"$freq$ - the frequency of sample collection in Hz (number of samples per second). If 0, the timer is not used and samples are acquired as quickly as possible.",
|
||||
},
|
||||
ret = "the actual sampling frequency that will be used, which might be different from the requested frequency, depending on the hardware"
|
||||
},
|
||||
|
||||
{ sig = "int #platform_adc_check_timer_id#( unsigned id, unsigned timer_id );",
|
||||
desc = "Checks whether a timer may be used with a particular ADC channel",
|
||||
args =
|
||||
@ -63,64 +85,4 @@ data_en =
|
||||
}
|
||||
}
|
||||
|
||||
data_pt =
|
||||
{
|
||||
-- Menu name
|
||||
menu_name = "ADC",
|
||||
|
||||
-- Title
|
||||
title = "eLua API - ADC",
|
||||
|
||||
-- Overview
|
||||
overview = "Interfaceamento com as funcões do ADC da MCU.",
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "int #platform_adc_exists#( unsigned id );",
|
||||
desc = [[Checa se a plataforma possui hardware para o Conversor AD especificado no argumento. Implementado em %src/common.c%, utiliza a macro $NUM_ADC$ que deve estar definida no arquivo $platform_conf.h$ da plataforma em questão. (veja @arch_overview.html#platforms@here@ para detalhes). Por exemplo:</p>
|
||||
~#define NUM_ADC 1 $// A Plataforma possui uma interface para ADC$~<p> ]],
|
||||
args = "$id$ - ADC ID",
|
||||
ret = "1 se a interface do ADC existir, 0 em caso contrário"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_op#( unsigned id, int op, u32 data );",
|
||||
desc = "Executes an operation on an ADC channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - ID do canal ADC",
|
||||
[[$op$ - A operação que deve ser executada. Valores possíveis em @#adc_operations@this enum@, conforme:
|
||||
<ul>
|
||||
<li>$PLATFORM_ADC_GET_MAXVAL$: Pega o maior valor de conversão que o canal pode fornecer, dependendo de sua resolução.</li>
|
||||
<li>$PLATFORM_ADC_SET_SMOOTHING$: Seta o tamanho do filtro atenuador de média móvel em $data$ </li>
|
||||
<li>$PLATFORM_ADC_SET_BLOCKING$: Seta se a amostragem deve aguardar novos valores (blocking)</li>
|
||||
<li>$PLATFORM_ADC_IS_DONE$: Checa se a amostragem foi completada</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_TIMER$: Seleciona um Timer para o controle da amostragem</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_CLOCK$: Seta a frequência de amostragem</li>
|
||||
</ul>]],
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_SET_SMOOTHING$, especifica o tamanho do filtro de média móvel (deve ser potência de 2). O valor 1 desabilita o filtro.",
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_SET_BLOCKING$, especifica se a amostragem é blocking ou não. Se 1, os pedidos só retornam quando as amostras tiverem sido obtidas ou a amostragem encerrada. Se 0, os pedidos retornam imediatamente, com o número de amostras já obtidas.",
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_OP_SET_TIMER$, especifica o Timer a ser usado para o controle da frequência de amostragem.",
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_OP_SET_CLOCK$, especifica a frequência de amostragem em Hz (número de amostras por segundo). Se 0, nenhum Timer é usado e a amostragem é feita o mais rapidamente possível."
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"O maior valor possível de ser obtido do conversor, quando $op$ == $PLATFORM_ADC_GET_MAXVAL$",
|
||||
"Flag informando se a conversão foi completada (1: sim, 0: não), quando $op$ == $PLATFORM_ADC_IS_DONE$. Também retorna 1 se nenhuma conversão foi solicitada.",
|
||||
"A frequência real de conversão que sera usada, quando $op$ == $PLATFORM_ADC_OP_SET_CLOCK$",
|
||||
"Indefinido para outras operações."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "int #platform_adc_check_timer_id#( unsigned id, unsigned timer_id );",
|
||||
desc = "Checa see um Timer pode ser usado com um ADC específico",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC ID",
|
||||
"$timer_id$ - Timer ID",
|
||||
},
|
||||
ret = "1 se o Timer pode ser usado para trigar um ADC. 0 em caso contrário",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -49,28 +49,44 @@ enum
|
||||
ret = "The actual frequency set on the PWM channel, which might differ from the $frequency$ parameter, depeding on the hardware",
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_op#( unsigned id, int op, u32 data );",
|
||||
desc = "Executes an operation on a PWM channel",
|
||||
{ sig = "u32 #platform_pwm_start#( unsigned id );",
|
||||
desc = "Starts PWM generation on the specified channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
[[$op$ - the operation that must be executed. It can take any value from @#pwm_operations@this enum@, as follows:
|
||||
<ul>
|
||||
<li>$PLATFORM_PWM_OP_START$: starts PWM generation on the specified channel.</li>
|
||||
<li>$PLATFORM_PWM_OP_STOP$: stops PWM generation on the specified channel.</li>
|
||||
<li>$PLATFORM_PWM_OP_SET_CLOCK$: sets the $base$ clock of the specified PWM channel (which will be used to generate the frequencies requested by
|
||||
@#platform_pwm_setup@platform_pwm_setup@) to $data$ hertz.</li>
|
||||
<li>$PLATFORM_PWM_OP_GET_CLOCK$: get the $base$ clock of the specified PWM channel.</li>
|
||||
</ul>]],
|
||||
"$data$ - when used with $op$ == $PLATFORM_PWM_OP_SET_CLOCK$ it is used to specify the value of the base clock. Not used with other operations."
|
||||
},
|
||||
ret =
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_stop#( unsigned id );",
|
||||
desc = "Stops PWM generation on the specified channel",
|
||||
args =
|
||||
{
|
||||
"the actual value of the base clock when $op$ == $PLATFORM_PWM_OP_SET_CLOCK$, which might be different than $data$ depending on the hardware",
|
||||
"the value of the base clock when $op$ == $PLATFORM_PWM_OP_GET_CLOCK$",
|
||||
"irrelevant for other operations"
|
||||
}
|
||||
}
|
||||
"$id$ - PWM channel ID",
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_set_clock#( unsigned id, u32 clock );",
|
||||
desc = [[Sets the $base$ clock of the specified PWM channel
|
||||
(which will be used to generate the frequencies requested by
|
||||
@#platform_pwm_setup@platform_pwm_setup@) to $data$ hertz.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
"$clock$ - the desired frequency of the base clock."
|
||||
},
|
||||
ret = [[The actual value of the base clock, which might be different
|
||||
from $data$ depending on the hardware]],
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_get_clock#( unsigned id );",
|
||||
desc = "Gets the $base$ clock of the specified PWM channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
"$clock$ - the desired frequency of the base clock."
|
||||
},
|
||||
ret = "the value of the base clock"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ data_en =
|
||||
"$clock$ - frequency to acquire samples at in Hz (number of samples per second), 0 to acquire as fast as possible.",
|
||||
"$timer_id$ - Timer channel ID to use to control ADC conversion. <strong>Note:</strong> At this time, a timer selection will apply to all channels on a given ADC peripheral."
|
||||
},
|
||||
ret = "$clock$ - actual acquisition frequency to be used"
|
||||
ret = "$clock$ - actual acquisition frequency that was set"
|
||||
},
|
||||
{ sig = "status = #adc.isdone#( id )",
|
||||
desc = "Check whether samples are still being acquired on a channel.",
|
||||
|
@ -31,7 +31,7 @@ $_C$. For example, to get the constants listed above declare your $PLATFORM_CPU_
|
||||
_C( INT_GPIOB ),\
|
||||
.................
|
||||
_C( INT_UDMA )~
|
||||
<p>It's worth to note that adding more constants does not increas RAM usage, only Flash usage, so you can expose as much constants as you need without worrying about RAM consumption.<br />
|
||||
<p>It's worth to note that adding more constants does not increase RAM usage, only Flash usage, so you can expose as many constants as you need without worrying about RAM consumption.<br />
|
||||
This mechanism is also used to expose interrupt IDs to the CPU module, check @inthandlers.html@here@ for an overview of eLua interrupt support.]]
|
||||
},
|
||||
},
|
||||
|
@ -63,7 +63,7 @@ data_en =
|
||||
desc = "Reads a number of bytes from a slave that has already acknowledged an @#i2c.address@i2c.address@ call. It acknowledges all the bytes received except for the last one.",
|
||||
args =
|
||||
{
|
||||
"$id$ - the ID of the SPI interface.",
|
||||
"$id$ - the ID of the I2C interface.",
|
||||
"$numbytes$ - the number of bytes to read."
|
||||
},
|
||||
ret = "a string with all the data read from the I2C interface."
|
||||
|
@ -111,8 +111,7 @@ argument. The IP is given as a string.]],
|
||||
"$port$ - the port to wait for connections from the remote system.",
|
||||
[[$timer_id (optional)$ - the timer ID of the timer used to timeout the accept function after a specified time. If this is specified, $timeout$ must also
|
||||
be specified.]],
|
||||
[[$timeout (optional)$ - the timeout after which the accept function returns if no connection was requested. If this is specified, $timer_id$ must also
|
||||
be specified.]]
|
||||
[[$timeout (optional)$ - the timeout, in microseconds, after which the accept function returns if no connection was requested.]]
|
||||
},
|
||||
ret =
|
||||
{
|
||||
@ -148,8 +147,7 @@ be specified.]]
|
||||
</ul>]],
|
||||
[[$timer_id (optional)$ - the timer ID of the timer used to timeout the recv function after a specified time. If this is specified, $timeout$ must also
|
||||
be specified.]],
|
||||
[[$timeout (optional)$ - the timeout after which the recv function returns if no connection was requested. If this is specified, $timer_id$ must also
|
||||
be specified.]]
|
||||
[[$timeout (optional)$ - the timeout, in microseconds, after which the recv function returns if no connection was requested.]]
|
||||
},
|
||||
ret =
|
||||
{
|
||||
|
@ -1,41 +0,0 @@
|
||||
-- eLua reference manual - platform data
|
||||
|
||||
data_en =
|
||||
{
|
||||
|
||||
-- Title
|
||||
title = "eLua reference manual - Mizar32 disp module",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "disp",
|
||||
|
||||
-- Overview
|
||||
overview = [[This module contains functions to drive the 16x2 character LED panel for the Mizar32.]],
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "#mizar32.disp.clear#()",
|
||||
desc = "Clear the display and move the cursor to the top left (position 1,1)."
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.disp.goto#( row, column )",
|
||||
desc = "Move the cursor to the specified row and column.",
|
||||
args =
|
||||
{
|
||||
"$row$ - A number (1 or 2) giving the row you want to move to.",
|
||||
"$column$ - A number (1 to 16) giving the character position within that row."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.disp.print#( message )",
|
||||
desc = "Display characters at the current cursor position, moving the cursor right after each character",
|
||||
args =
|
||||
{
|
||||
"$message$ - A string of ASCII text to be written on the display."
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data_pt = data_en
|
88
doc/eluadoc/refman_ps_mizar32_lcd.lua
Normal file
88
doc/eluadoc/refman_ps_mizar32_lcd.lua
Normal file
@ -0,0 +1,88 @@
|
||||
-- eLaa reference manual - platform data
|
||||
|
||||
data_en =
|
||||
{
|
||||
|
||||
-- Title
|
||||
title = "eLua reference manual - Mizar32 LCD module",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "lcd",
|
||||
|
||||
-- Overview
|
||||
overview = [[This module contains functions to drive the two-line character LCD panel of the Mizar32 display module.</p>
|
||||
<p>Physically, the display has 16 characters per line but internally it has a 40 characters by two line memory. It displays 16 of those 40 columns at a time, with various ways to determine which of the 40 columns appear in the 16-column display. If you just want to display 16x2 characters, the $reset$, $goto$ and $print$ functions are enough to do this.]],
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "#mizar32.lcd.reset#()",
|
||||
desc = "Initialises the display, resetting everything to as initial state: clear screen, no cursor, displaying columns 1-16 of the 40-column memory, ready to print at (1,1), writing text from left to right and moving the cursor one place right after each character. You don't %have% to call $reset$ at the start of your program, but doing so does will ensure that your program still works if the display has been left in a funny state by some previous run."
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.setup#( display_shift, right_to_left )",
|
||||
desc = "This can be used to set some of the stranger operating modes of the LCD display. Both parameters are optional and if you omit them, they default to $false$, which sets sensible mode.",
|
||||
args =
|
||||
{
|
||||
[[$display_shift$ - If $true$, then with each character you subsequently print, the cursor will move by one place in the character memory as usual but the display's contents will also move by one position horizontally so that the cursor remains in the same column of the physical display. This can be used to achieve "scrolling text" effects. Note, however, that when the cursor passes from column 40 to column 1 or vice versa, it flips over to the other row.]],
|
||||
"$right_to_left$ - If $true$, text will be printed right-to-left: the cursor will move one position to the left in the character memory and, if display shifting is also enabled, the display will shift so as to keep the cursor in the same column on the screen."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.clear#()",
|
||||
desc = "Clears the display, move the cursor to the top left (position 1,1) and reset the display shift to show columns 1-16."
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.home#()",
|
||||
desc = "Moves the cursor to the top left (position 1,1) and reset the display shift."
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.goto#( row, column )",
|
||||
desc = "Move the cursor to the specified row and column.",
|
||||
args =
|
||||
{
|
||||
"$row$ - A number (1 or 2) giving the row you want to move to.",
|
||||
"$column$ - A number (1 to 40) giving the position within that row in the character memory."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.print#( [data1] [, data2] ... [datan] )",
|
||||
desc = "Writes into the LCD character memory starting at the current cursor position. The cursor will advance by one position for each character printed. When it goes past column 40, it moves to column 1 of the other line, (and vice versa when printing right-to-left).",
|
||||
args =
|
||||
{
|
||||
"$data$ - Each item of data can be a string or an integer. Strings are the normal way to display messages of ASCII text. An integer parameter should have a value from 0 to 255 to display a single character, which can be one of the user-defined characters 0-7, the regular ASCII characters 32-125 plus 126 and 127 for right- and left-pointing arrows and the chinese, greek and mathematical symbols with codes 160-255."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.cursor#( what )",
|
||||
desc = "Sets the type of cursor that is displayed at the cursor position or move the cursor left or right.",
|
||||
args =
|
||||
{
|
||||
[[$what$ - A string to say what should be done:
|
||||
<p>$"none"$, $"line"$ or $"block"$ will display, respectively, no visible cursor, a constant underline or a blinking solid block at the cursor position.
|
||||
<p>$"left"$ or $"right"$ move the cursor one position left or right in the character memory and on the display without changing the underlying characters. The display never shifts in this case and, as usual, the cursor wraps between column 40 of one row and column 1 of the other.]]
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.display#( what )",
|
||||
desc = "Turns the physical display on or off, or shifts the displayed characters left or right.",
|
||||
args =
|
||||
{
|
||||
[[$what$ - A string to say what should be done:
|
||||
<p>$"off"$ and $"on"$ turn the physical display off or back on again. While the display is off it appears blank but the contents of the character memory, the position and type of cursor, user-defined characters and setup mode are all remembered and you can write to the character memory and perform all other operations while the display is off. This allows you to update the display without the viewer seeing too much flickering.
|
||||
<p>$"left"$ or $"right"$ shift the displayed characters one place left or right. For example, if it was displaying the usual columns 1-16 and you say %mizar32.lcd.display("left")%, it will then display columns 2-17: the visible characters move left but the window onto the character memory moves right. ]],
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.definechar#( code, glyph )",
|
||||
desc = "Programs one of the eight user-definable characters whose codes are 0 to 7. When it has been defined, a character can be displayed using $mizar32.lcd.print(n)$, where $n$ is a number from 0 to 7. If the character in question is already being displayed, its visible form will change immediately on the display. At power-on, the 8 characters are defined as random garbage.",
|
||||
args =
|
||||
{
|
||||
"$code$ - A number (0 to 7) saying which of the characters you wish to redefine.",
|
||||
"$glyph$ - A table of up to eight numbers giving the bit-patterns for the eight rows of the character, in order from top to bottom. Each of these number is a value from 0 to 31, to define which of the 5 bits in the row should be black. The pixels' values from left to right are 16, 8, 4, 2 and 1. For example, { 1, 3, 7, 15, 31, 15, 7, 3, 1, 0 } would define a left-pointing solid triangle in the top 7 rows. Extra rows are ignored, and missing rows are blanked."
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data_pt = data_en
|
@ -10,7 +10,7 @@ data_en =
|
||||
menu_name = "pio",
|
||||
|
||||
-- Overview
|
||||
overview = [[This module contains functions for accesing the particular features of the PIO subsystem of the STR9 family of CPUs. This subsystem is very flexible, allowing things like
|
||||
overview = [[This module contains functions for accessing the particular features of the PIO subsystem of the STR9 family of CPUs. This subsystem is very flexible, allowing things like
|
||||
configurable output types (push-pull or open collector), multiple alternate functions for the PIO pins, and others. For a full description of the STR9 PIO module check the STR9 CPU
|
||||
Reference manual, available from ST at @http://www.st.com/mcu/devicedocs-STR912FAW44-101.html@this address@. Note that this module is a supplement of the platform independent
|
||||
@refman_gen_pio.html@pio@ module, not a replacement. Use this module only for setting up the STR9 PIO pins, and the @refman_gen_pio.html@pio@ module for all the other PIO related operations.]],
|
||||
|
@ -1,60 +0,0 @@
|
||||
-- eLua reference manual - str9 platform specific rtc - Real Time Clock - data
|
||||
|
||||
data_en =
|
||||
{
|
||||
|
||||
-- Title
|
||||
title = "eLua reference manual - STR9 rtc module",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "rtc",
|
||||
|
||||
-- Overview
|
||||
overview = [[This module contains functions for accesing the particular features of the RTC - Real Time Clock - subsystem of the STR9 family of CPUs.
|
||||
This internal subsystem offers functions to keep track of a real time clock calendar, as well as some other features like alarms and auxiliar functions.
|
||||
Reference manual, available from ST at @http://www.st.com/mcu/devicedocs-STR912FAW44-101.html@this address@.]],
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "#str9.rtc.settime#( time )",
|
||||
desc = "Sets the Real Time Clock time to a specific time of the day.",
|
||||
args =
|
||||
{
|
||||
"$time$ - a string in the format 'hh:mm:ss' or a Lua table with 'hour', 'min' and 'sec' string fields.",
|
||||
},
|
||||
ret = "nothing.",
|
||||
ex = 'str9.settime("14:25:00") - Sets the RTC time to 14 hour 25 minutes, 2:25 PM',
|
||||
},
|
||||
{ sig = "#str9.rtc.gettime#( format )",
|
||||
desc = "Gets the time kept by the Real Time Clock.",
|
||||
args =
|
||||
{
|
||||
"$format$ - the string '*s' to return the time as a string 'hh:mm:ss' or '*t' to return as a Lua table with string fields 'hour', 'min' and 'sec'.",
|
||||
},
|
||||
ret = "a string or a Lua table, according to the format argument.",
|
||||
ex = 'now = str9.rtc.gettime( "*s" ) - now receives a sting like "14:25:05", now = str9.rtc.gettime( "*t" ) - now receives the Lua table { hour = 14, min = 25, sec = 05 }',
|
||||
},
|
||||
{ sig = "#str9.rtc.setdate#( date )",
|
||||
desc = "Sets the Real Time Clock date to a specific date.",
|
||||
args =
|
||||
{
|
||||
"$date$ - a string in the format 'dd/mm/yyyy' or a Lua table with 'day', 'month' and 'year' string fields.",
|
||||
},
|
||||
ret = "nothing.",
|
||||
ex = 'str9.rtc.setdate( "31/08/1960" ) - set the RTC date to August 31st 1960',
|
||||
},
|
||||
{ sig = "#str9.rtc.getdate#( format )",
|
||||
desc = "Gets the date kept by the Real Time Clock.",
|
||||
args =
|
||||
{
|
||||
"$format$ - the string '*s' to return the date as a string 'dd/mm/yyyy' or '*t' to return as a Lua table with string fields 'day', 'month' and 'year'.",
|
||||
},
|
||||
ret = "a string or a Lua table, according to the format argument.",
|
||||
ex = 'today = str9.rtc.getdate( "*s" ) - today receives a string like "14/12/2010", meaning December 14th of 2010, today = str9.rtc.getdate( "*t" ) - today receives the Lua table { day = 14, month = 12, year = 2010 }',
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
data_pt = data_en
|
@ -9,7 +9,7 @@ $$HEADER$$
|
||||
0, PORTB will have 1 and so on. Similarly, the second SPI interface (SPI1) of the MCU will probably have an id equal to 1. However, this is not a strict
|
||||
rule. The implementation of the platform interface might choose to expose only some of the peripherals (components) of the MCU, thus this rule might be
|
||||
broken. For example, if a board has 3 UARTs, but for some reason the second UART (UART1) is dedicated and can't be touched by <b>eLua</b>, then UART0 will have the id 0 and UART2 will
|
||||
have the id 1, so UART1 won't ever be accesible to the code. </p>
|
||||
have the id 1, so UART1 won't ever be accessible to the code. </p>
|
||||
<p>With some exceptions (most notably the low-level support functions), the different modules supported by the platform interface are
|
||||
mirrored more or less accurately in separate Lua modules that can be used directly from <b>eLua</b>. Check the reference manual for a
|
||||
complete description of these modules.</p>
|
||||
|
@ -5,7 +5,7 @@ $$HEADER$$
|
||||
<li><b>the ROM file system</b>: a very simple, very low footprint read-only file system that can be included in the <b>eLua</b> binary image. Check <a href="arch_romfs.html">here</a> for details.</li>
|
||||
<li><b>the FAT file system</b>: a read-write FAT file system implementation (platform independent) that can currently be used with SD/MMC memory cards. Check <a href="fatfs.html">here</a> for
|
||||
details. <b>(new in 0.7)</b></li>
|
||||
<li><b>the remote file system (RFS)</b>: a read-write file system that allows eLua to 'share' a directory on a PC, effectively accesing
|
||||
<li><b>the remote file system (RFS)</b>: a read-write file system that allows eLua to 'share' a directory on a PC, effectively accessing
|
||||
its contents as if it was a local file system. Check <a href="arch_rfs.html">here</a> for details. <b>(new in 0.8)</b></li>
|
||||
</ul>
|
||||
$$FOOTER$$
|
||||
|
@ -9,7 +9,7 @@ $$HEADER$$
|
||||
0, PORTB will have 1 and so on. Similarly, the second SPI interface (SPI1) of the MCU will probably have an id equal to 1. However, this is not a strict
|
||||
rule. The implementation of the platform interface might choose to expose only some of the peripherals (components) of the MCU, thus this rule might be
|
||||
broken. For example, if a board has 3 UARTs, but for some reason the second UART (UART1) is dedicated and can't be touched by <b>eLua</b>, then UART0 will have the id 0 and UART2 will
|
||||
have the id 1, so UART1 won't ever be accesible to the code.</p>
|
||||
have the id 1, so UART1 won't ever be accessible to the code.</p>
|
||||
<p>With some exceptions (most notably the low-level support functions), the different modules supported by the platform interface are
|
||||
mirrored more or less accurately in separate Lua modules that can be used directly from <b>eLua</b>. Check <a href="refman_gen.html">the reference manual</a> for a
|
||||
complete description of these modules.</p>
|
||||
|
@ -9,6 +9,9 @@
|
||||
#define BUILD_RPC
|
||||
#define LUARPC_ENABLE_SERIAL
|
||||
|
||||
#define LUA_PLATFORM_LIBS_REG \
|
||||
{LUA_OSLIBNAME, luaopen_os}
|
||||
|
||||
#define LUA_PLATFORM_LIBS_ROM \
|
||||
_ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )\
|
||||
_ROM( AUXLIB_BITARRAY, luaopen_bitarray, bitarray_map )\
|
||||
|
@ -198,19 +198,13 @@ u32 platform_timer_get_diff_us( unsigned id, timer_data_type end, timer_data_typ
|
||||
// There are 16 "virtual" PWM channels (PWM0...PWM15)
|
||||
#define PLATFORM_PWM_TOTAL 16
|
||||
|
||||
// PWM operations
|
||||
enum
|
||||
{
|
||||
PLATFORM_PWM_OP_START,
|
||||
PLATFORM_PWM_OP_STOP,
|
||||
PLATFORM_PWM_OP_SET_CLOCK,
|
||||
PLATFORM_PWM_OP_GET_CLOCK
|
||||
};
|
||||
|
||||
// The platform PWM functions
|
||||
int platform_pwm_exists( unsigned id );
|
||||
u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty );
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data );
|
||||
void platform_pwm_start( unsigned id );
|
||||
void platform_pwm_stop( unsigned id );
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 data );
|
||||
u32 platform_pwm_get_clock( unsigned id );
|
||||
|
||||
// *****************************************************************************
|
||||
// CPU specific functions
|
||||
@ -235,27 +229,22 @@ u32 platform_cpu_get_frequency();
|
||||
// *****************************************************************************
|
||||
// The platform ADC functions
|
||||
|
||||
enum
|
||||
{
|
||||
PLATFORM_ADC_GET_MAXVAL,
|
||||
PLATFORM_ADC_SET_SMOOTHING,
|
||||
PLATFORM_ADC_SET_BLOCKING,
|
||||
PLATFORM_ADC_SET_FREERUNNING,
|
||||
PLATFORM_ADC_IS_DONE,
|
||||
PLATFORM_ADC_OP_SET_TIMER,
|
||||
PLATFORM_ADC_OP_SET_CLOCK,
|
||||
};
|
||||
|
||||
// Functions requiring platform-specific implementation
|
||||
int platform_adc_update_sequence();
|
||||
int platform_adc_start_sequence();
|
||||
void platform_adc_stop( unsigned id );
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency);
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency);
|
||||
|
||||
// ADC Common Functions
|
||||
int platform_adc_exists( unsigned id );
|
||||
int platform_adc_check_timer_id( unsigned id, unsigned timer_id );
|
||||
u32 platform_adc_op( unsigned id, int op, u32 data );
|
||||
int platform_adc_exists( unsigned id );
|
||||
int platform_adc_check_timer_id( unsigned id, unsigned timer_id );
|
||||
u32 platform_adc_get_maxval( unsigned id );
|
||||
u32 platform_adc_set_smoothing( unsigned id, u32 length );
|
||||
void platform_adc_set_blocking( unsigned id, u32 mode );
|
||||
void platform_adc_set_freerunning( unsigned id, u32 mode );
|
||||
u32 platform_adc_is_done( unsigned id );
|
||||
void platform_adc_set_timer( unsigned id, u32 timer );
|
||||
u32 platform_adc_set_clock( unsigned id, u32 freq );
|
||||
|
||||
// *****************************************************************************
|
||||
// I2C platform interface
|
||||
|
74
src/common.c
74
src/common.c
@ -294,47 +294,41 @@ int platform_adc_exists( unsigned id )
|
||||
|
||||
#ifdef BUILD_ADC
|
||||
|
||||
u32 platform_adc_op( unsigned id, int op, u32 data )
|
||||
{
|
||||
elua_adc_ch_state *s = adc_get_ch_state( id );
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
u32 res = 0;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_ADC_GET_MAXVAL:
|
||||
res = pow( 2, ADC_BIT_RESOLUTION ) - 1;
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_SET_SMOOTHING:
|
||||
res = adc_update_smoothing( id, ( u8 )intlog2( ( unsigned ) data ) );
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_SET_BLOCKING:
|
||||
s->blocking = data;
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_IS_DONE:
|
||||
res = ( s->op_pending == 0 );
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_OP_SET_TIMER:
|
||||
if ( d->timer_id != data )
|
||||
d->running = 0;
|
||||
platform_adc_stop( id );
|
||||
d->timer_id = data;
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_OP_SET_CLOCK:
|
||||
res = platform_adc_setclock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_SET_FREERUNNING:
|
||||
s->freerunning = data;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
u32 platform_adc_get_maxval( unsigned id )
|
||||
{
|
||||
return pow( 2, ADC_BIT_RESOLUTION ) - 1;
|
||||
}
|
||||
|
||||
u32 platform_adc_set_smoothing( unsigned id, u32 length )
|
||||
{
|
||||
return adc_update_smoothing( id, ( u8 )intlog2( ( unsigned ) length ) );
|
||||
}
|
||||
|
||||
void platform_adc_set_blocking( unsigned id, u32 mode )
|
||||
{
|
||||
adc_get_ch_state( id )->blocking = mode;
|
||||
}
|
||||
|
||||
void platform_adc_set_freerunning( unsigned id, u32 mode )
|
||||
{
|
||||
adc_get_ch_state( id )->freerunning = mode;
|
||||
}
|
||||
|
||||
u32 platform_adc_is_done( unsigned id )
|
||||
{
|
||||
return adc_get_ch_state( id )->op_pending == 0;
|
||||
}
|
||||
|
||||
void platform_adc_set_timer( unsigned id, u32 timer )
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
||||
if ( d->timer_id != timer )
|
||||
d->running = 0;
|
||||
platform_adc_stop( id );
|
||||
d->timer_id = timer;
|
||||
}
|
||||
|
||||
#endif // #ifdef BUILD_ADC
|
||||
|
||||
// ****************************************************************************
|
||||
|
@ -126,7 +126,7 @@ void adc_init_ch_state( unsigned id )
|
||||
#endif
|
||||
|
||||
// Set to run as fast as possible
|
||||
platform_adc_setclock( id, 0 );
|
||||
platform_adc_set_clock( id, 0 );
|
||||
}
|
||||
|
||||
void adc_init_dev_state( unsigned dev_id )
|
||||
|
@ -34,6 +34,8 @@ static int math_abs (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
static int math_sin (lua_State *L) {
|
||||
lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
@ -107,6 +109,20 @@ static int math_modf (lua_State *L) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
#else // #ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
// In integer math, floor() and ceil() give the same value;
|
||||
// having them in the integer library allows you to write code that
|
||||
// works in both integer and floating point versions of Lua.
|
||||
// This identity function is used for them.
|
||||
|
||||
static int math_identity (lua_State *L) {
|
||||
lua_pushnumber(L, luaL_checknumber(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // #ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
#ifdef LUA_NUMBER_INTEGRAL
|
||||
// Integer square root for integer version
|
||||
static lua_Number isqrt(lua_Number x)
|
||||
@ -142,6 +158,8 @@ static int math_sqrt (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
static int math_pow (lua_State *L) {
|
||||
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
||||
return 1;
|
||||
@ -184,7 +202,7 @@ static int math_ldexp (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif // #ifdef LUA_NUMBER_INTEGRAL
|
||||
|
||||
static int math_min (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
@ -284,6 +302,8 @@ static int math_randomseed (lua_State *L) {
|
||||
const LUA_REG_TYPE math_map[] = {
|
||||
#ifdef LUA_NUMBER_INTEGRAL
|
||||
{LSTRKEY("abs"), LFUNCVAL(math_abs)},
|
||||
{LSTRKEY("ceil"), LFUNCVAL(math_identity)},
|
||||
{LSTRKEY("floor"), LFUNCVAL(math_identity)},
|
||||
{LSTRKEY("max"), LFUNCVAL(math_max)},
|
||||
{LSTRKEY("min"), LFUNCVAL(math_min)},
|
||||
{LSTRKEY("random"), LFUNCVAL(math_random)},
|
||||
|
@ -20,30 +20,30 @@ static int adc_maxval( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
res = platform_adc_op( id, PLATFORM_ADC_GET_MAXVAL, 0 );
|
||||
res = platform_adc_get_maxval( id );
|
||||
lua_pushinteger( L, res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: realclock = setclock( id, clock, [timer_id] )
|
||||
// Lua: realclock = setclock( id, freq, [timer_id] )
|
||||
static int adc_setclock( lua_State* L )
|
||||
{
|
||||
u32 clock;
|
||||
u32 freq;
|
||||
unsigned id, timer_id = 0;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
clock = luaL_checkinteger( L, 2 );
|
||||
if ( clock > 0 )
|
||||
freq = luaL_checkinteger( L, 2 );
|
||||
if ( freq > 0 )
|
||||
{
|
||||
timer_id = luaL_checkinteger( L, 3 );
|
||||
MOD_CHECK_ID( timer, timer_id );
|
||||
MOD_CHECK_RES_ID( adc, id, timer, timer_id );
|
||||
}
|
||||
|
||||
platform_adc_op( id, PLATFORM_ADC_OP_SET_TIMER, timer_id );
|
||||
clock = platform_adc_op( id, PLATFORM_ADC_OP_SET_CLOCK, clock );
|
||||
lua_pushinteger( L, clock );
|
||||
platform_adc_set_timer( id, timer_id );
|
||||
freq = platform_adc_set_clock( id, freq );
|
||||
lua_pushinteger( L, freq );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ static int adc_isdone( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
lua_pushinteger( L, platform_adc_op( id, PLATFORM_ADC_IS_DONE, 0 ) );
|
||||
lua_pushinteger( L, platform_adc_is_done( id ) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ static int adc_setblocking( lua_State* L )
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
mode = luaL_checkinteger( L, 2 );
|
||||
platform_adc_op( id, PLATFORM_ADC_SET_BLOCKING, mode );
|
||||
platform_adc_set_blocking( id, mode );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ static int adc_setsmoothing( lua_State* L )
|
||||
length = luaL_checkinteger( L, 2 );
|
||||
if ( !( length & ( length - 1 ) ) )
|
||||
{
|
||||
res = platform_adc_op( id, PLATFORM_ADC_SET_SMOOTHING, length );
|
||||
res = platform_adc_set_smoothing( id, length );
|
||||
if ( res == PLATFORM_ERR )
|
||||
return luaL_error( L, "Buffer allocation failed." );
|
||||
else
|
||||
|
@ -68,7 +68,9 @@ static int i2c_write( lua_State *L )
|
||||
return luaL_error( L, "invalid number of arguments" );
|
||||
for( argn = 2; argn <= lua_gettop( L ); argn ++ )
|
||||
{
|
||||
if( lua_isnumber( L, argn ) )
|
||||
// lua_isnumber() would silently convert a string of digits to an integer
|
||||
// whereas here strings are handled separately.
|
||||
if( lua_type( L, argn ) == LUA_TNUMBER )
|
||||
{
|
||||
numdata = ( int )luaL_checkinteger( L, argn );
|
||||
if( numdata < 0 || numdata > 255 )
|
||||
|
@ -31,7 +31,7 @@ static int pwm_start( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
platform_pwm_op( id, PLATFORM_PWM_OP_START, 0 );
|
||||
platform_pwm_start( id );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ static int pwm_stop( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
platform_pwm_op( id, PLATFORM_PWM_OP_STOP, 0 );
|
||||
platform_pwm_stop( id );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ static int pwm_setclock( lua_State* L )
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
clk = luaL_checkinteger( L, 2 );
|
||||
clk = platform_pwm_op( id, PLATFORM_PWM_OP_SET_CLOCK, clk );
|
||||
clk = platform_pwm_set_clock( id, clk );
|
||||
lua_pushinteger( L, clk );
|
||||
return 1;
|
||||
}
|
||||
@ -68,7 +68,7 @@ static int pwm_getclock( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
clk = platform_pwm_op( id, PLATFORM_PWM_OP_GET_CLOCK, 0 );
|
||||
clk = platform_pwm_get_clock( id );
|
||||
lua_pushinteger( L, clk );
|
||||
return 1;
|
||||
}
|
||||
|
@ -133,8 +133,10 @@ static int tmr_set_match_int( lua_State *L )
|
||||
res = platform_timer_set_match_int( id, ( u32 )luaL_checknumber( L, 2 ), ( int )luaL_checkinteger( L, 3 ) );
|
||||
if( res == PLATFORM_TIMER_INT_TOO_SHORT )
|
||||
return luaL_error( L, "timer interval too small" );
|
||||
else if( res == PLATFORM_TIMER_INT_TOO_LONG )
|
||||
return luaL_error( L, "timer interval too long" );
|
||||
else if( res == PLATFORM_TIMER_INT_INVALID_ID )
|
||||
return luaL_error( L, "mach interrupt cannot be set on this timer" );
|
||||
return luaL_error( L, "match interrupt cannot be set on this timer" );
|
||||
return 0;
|
||||
}
|
||||
#endif // #ifdef BUILD_LUA_INT_HANDLERS
|
||||
|
@ -338,8 +338,8 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
// PWM pins
|
||||
static const Pin pwm_pins[] = { PIN_PWMC_PWM0, PIN_PWMC_PWM1, PIN_PWMC_PWM2, PIN_PWMC_PWM3 };
|
||||
|
||||
// Helper function: return the PWM clock
|
||||
static u32 platform_pwm_get_clock( unsigned id )
|
||||
// Return the PWM clock
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
u32 cfg = AT91C_BASE_PWMC->PWMC_CH[ id ].PWMC_CMR;
|
||||
u16 clkdata;
|
||||
@ -358,8 +358,8 @@ static u32 platform_pwm_get_clock( unsigned id )
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function: set the PWM clock
|
||||
static u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
// Set the PWM clock
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
if( id < 2 )
|
||||
PWMC_ConfigureClocks( clock, 0, BOARD_MCK );
|
||||
@ -386,30 +386,14 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return pwmclk / period;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
u32 res = 0;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_pwm_get_clock( id );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
PIO_Configure( pwm_pins + id, 1 );
|
||||
res = AT91C_BASE_PWMC->PWMC_ISR;
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
platform_pio_op( 1, 1 << ( 19 + id ), PLATFORM_IO_PIN_DIR_INPUT );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
volatile u32 dummy;
|
||||
PIO_Configure( pwm_pins + id, 1 );
|
||||
dummy = AT91C_BASE_PWMC->PWMC_ISR;
|
||||
}
|
||||
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
platform_pio_op( 1, 1 << ( 19 + id ), PLATFORM_IO_PIN_DIR_INPUT );
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define BUILD_CON_GENERIC
|
||||
//#define BUILD_RPC
|
||||
#define BUILD_C_INT_HANDLERS
|
||||
#define BUILD_ADC
|
||||
|
||||
// *****************************************************************************
|
||||
// UART/Timer IDs configuration data (used in main.c)
|
||||
@ -43,6 +44,12 @@
|
||||
#define BUILD_RPC
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_ADC
|
||||
#define ADCLINE _ROM( AUXLIB_ADC, luaopen_adc, adc_map )
|
||||
#else
|
||||
#define ADCLINE
|
||||
#endif
|
||||
|
||||
#if defined( BUILD_RPC )
|
||||
#define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )
|
||||
#else
|
||||
@ -57,6 +64,7 @@
|
||||
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
|
||||
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
|
||||
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
|
||||
ADCLINE\
|
||||
RPCLINE\
|
||||
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
|
||||
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
|
||||
@ -78,8 +86,8 @@
|
||||
#else
|
||||
#define NUM_TIMER 3
|
||||
#endif
|
||||
#define NUM_PWM 0
|
||||
#define NUM_ADC 0
|
||||
#define NUM_PWM 7
|
||||
#define NUM_ADC 8
|
||||
#define NUM_CAN 0
|
||||
|
||||
// RPC boot options
|
||||
@ -91,6 +99,11 @@
|
||||
#define BUF_ENABLE_UART
|
||||
#define CON_BUF_SIZE BUF_SIZE_128
|
||||
|
||||
// ADC Configuration Params
|
||||
#define ADC_BIT_RESOLUTION 10
|
||||
#define BUF_ENABLE_ADC
|
||||
#define ADC_BUF_SIZE BUF_SIZE_2
|
||||
|
||||
// SD/MMC Filesystem Setup
|
||||
#define MMCFS_TICK_HZ 10
|
||||
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )
|
||||
|
@ -22,6 +22,7 @@
|
||||
//#define BUILD_RPC
|
||||
#define BUF_ENABLE_UART
|
||||
#define BUILD_C_INT_HANDLERS
|
||||
#define BUILD_LUA_INT_HANDLERS
|
||||
//#define BUILD_RFS
|
||||
//#define BUILD_SERMUX
|
||||
|
||||
@ -32,9 +33,9 @@
|
||||
// Build options for 256KB and 512KB flash
|
||||
# define RAM_SIZE 0x10000
|
||||
# define BUILD_ADC
|
||||
# define BUILD_LCD
|
||||
# define BUILD_TERM
|
||||
# define BUILD_UIP
|
||||
# define ENABLE_DISP
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
@ -47,7 +48,7 @@
|
||||
// Auxiliary libraries that will be compiled for this platform
|
||||
|
||||
// The name of the platform specific libs table
|
||||
#ifdef ENABLE_DISP
|
||||
#ifdef BUILD_LCD
|
||||
#define PS_LIB_TABLE_NAME "mizar32"
|
||||
#endif
|
||||
|
||||
@ -109,7 +110,7 @@
|
||||
#define RPCLINE
|
||||
#endif
|
||||
|
||||
#ifdef PS_LIB_TABLE_NAME
|
||||
#if defined( PS_LIB_TABLE_NAME )
|
||||
#define PLATLINE _ROM( PS_LIB_TABLE_NAME, luaopen_platform, platform_map )
|
||||
#else
|
||||
#define PLATLINE
|
||||
|
@ -1,6 +1,6 @@
|
||||
-- Configuration file for the AVR32 microcontrollers
|
||||
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c i2c.c ethernet.c disp.c"
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c i2c.c ethernet.c lcd.c"
|
||||
addm( "FORAVR32" )
|
||||
|
||||
-- See board.h for possible BOARD values.
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Configuration file for the AVR32 microcontrollers
|
||||
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c i2c.c ethernet.c disp.c"
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c i2c.c ethernet.c lcd.c"
|
||||
comp.Append(CPPDEFINES = 'FORAVR32')
|
||||
|
||||
# See board.h for possible BOARD values.
|
||||
|
@ -1,115 +0,0 @@
|
||||
// eLua module for Mizar32 LCD character display
|
||||
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "lrotable.h"
|
||||
#include "platform_conf.h"
|
||||
|
||||
#include "disp.h"
|
||||
#include "i2c.h"
|
||||
|
||||
// Declaration to save/restore the I2C clock rate
|
||||
extern u32 i2c_delay;
|
||||
static u32 old_i2c_delay;
|
||||
|
||||
// Functions that bracket all I2C packets to the LCD module,
|
||||
// to save, change and restore the I2C clock rate.
|
||||
static void disp_start()
|
||||
{
|
||||
old_i2c_delay = i2c_delay;
|
||||
i2c_delay = REQ_CPU_FREQ / DISP_BUS_FREQ / 2;
|
||||
}
|
||||
|
||||
static void disp_stop()
|
||||
{
|
||||
i2c_delay = old_i2c_delay;
|
||||
}
|
||||
|
||||
// Utility function: pause for N * 5ms
|
||||
static void disp_delay(unsigned long n)
|
||||
{
|
||||
// Code stolen from sdramc.c::sdramc_ck_delay()
|
||||
|
||||
// Use the CPU cycle counter (CPU and HSB clocks are the same).
|
||||
u32 delay_start_cycle = Get_system_register(AVR32_COUNT);
|
||||
u32 delay_end_cycle = delay_start_cycle + n * DISP_DELAY_TICKS;
|
||||
|
||||
// To be safer, the end of wait is based on an inequality test, so CPU cycle
|
||||
// counter wrap around is checked.
|
||||
if (delay_start_cycle > delay_end_cycle)
|
||||
{
|
||||
while ((unsigned long)Get_system_register(AVR32_COUNT) > delay_end_cycle);
|
||||
}
|
||||
while ((unsigned long)Get_system_register(AVR32_COUNT) < delay_end_cycle);
|
||||
}
|
||||
|
||||
// Generic function to emit an LCD command byte, normally used in a tail call.
|
||||
static int disp_command(unsigned char command)
|
||||
{
|
||||
disp_start();
|
||||
i2c_start_cond();
|
||||
i2c_write_byte( DISP_CMD );
|
||||
i2c_write_byte( command );
|
||||
i2c_stop_cond();
|
||||
disp_stop();
|
||||
disp_delay(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Lua: mizar32.disp.clear()
|
||||
static int disp_clear(lua_State *L) {
|
||||
return disp_command( DISP_CMD_CLEAR );
|
||||
}
|
||||
|
||||
//Lua: mizar32.disp.goto( row, col )
|
||||
static int disp_goto(lua_State *L) {
|
||||
unsigned row = luaL_checkinteger( L, 1 );
|
||||
unsigned col = luaL_checkinteger( L, 2 );
|
||||
unsigned address;
|
||||
|
||||
if ( row < 1 || row > 2 || col < 1 || col > 16 ) {
|
||||
return luaL_error( L, "row/column must be 1-2 and 1-16" );
|
||||
}
|
||||
|
||||
address = ( row - 1 ) * 0x40 + ( col - 1 ) ;
|
||||
|
||||
return disp_command( DISP_CMD_DDADDR + address );
|
||||
}
|
||||
|
||||
//Lua: mizar32.disp.print( string )
|
||||
static int disp_print(lua_State *L) {
|
||||
const char *str = luaL_checkstring( L, 1 );
|
||||
int nbytes = 0;
|
||||
|
||||
disp_start();
|
||||
i2c_start_cond();
|
||||
i2c_write_byte( DISP_DATA );
|
||||
// Mizar32 LCD module has a maximum of 32 bytes per packet
|
||||
while ( *str && nbytes < 32 ) {
|
||||
i2c_write_byte( *str++ );
|
||||
nbytes++;
|
||||
}
|
||||
i2c_stop_cond();
|
||||
disp_stop();
|
||||
disp_delay(nbytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
|
||||
// Module function map
|
||||
const LUA_REG_TYPE disp_map[] =
|
||||
{
|
||||
{ LSTRKEY( "clear" ), LFUNCVAL( disp_clear ) },
|
||||
{ LSTRKEY( "goto" ), LFUNCVAL( disp_goto ) },
|
||||
{ LSTRKEY( "print" ), LFUNCVAL( disp_print ) },
|
||||
};
|
||||
|
||||
LUALIB_API int luaopen_disp( lua_State *L )
|
||||
{
|
||||
LREGISTER( L, AUXLIB_DISP, disp_map );
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
// Mizar32 LCD character display
|
||||
|
||||
#ifndef __DISP_H__
|
||||
#define __DISP_H__
|
||||
|
||||
// See the Ampire datasheet http://home.comet.bg/datasheets/LCD/AC-162B.pdf
|
||||
// and http://embeddedtutorial.com/2010/01/interfacing-lcd-with-8051/
|
||||
|
||||
// I2C bus frequency that the LCD display runs at: 20kHz max
|
||||
#define DISP_BUS_FREQ 20000
|
||||
|
||||
// Pause required after every command byte, and n*delay when sending N
|
||||
// characters of data (or of commands): 5 milliseconds
|
||||
// Expressed in CPU clock ticks.
|
||||
// 5 and 6ms seem not to work when doing
|
||||
// mizar32.disp.clear() mizar32.disp.print("Hello world")
|
||||
// or
|
||||
// for i = 1,16 do mizar32.disp.goto(2,i) mizar32.disp.print("X") end
|
||||
// but 7ms works for both.
|
||||
#define DISP_DELAY_TICKS (REQ_CPU_FREQ * 7 / 1000)
|
||||
|
||||
// I2C slave addresses for command bytes and data strings
|
||||
// Command address is followed by a dingle byte giving the command to perform
|
||||
// Data address is followed by multiple bytes of ASCII data to display
|
||||
// on the character display at the current cursor location.
|
||||
#define DISP_CMD 0xF6
|
||||
#define DISP_DATA 0xF2
|
||||
|
||||
// Command bytes
|
||||
|
||||
// "Clear display: Write "20H" to DDRAM and set DDRAM address to "00H" from AC"
|
||||
#define DISP_CMD_CLEAR 1
|
||||
|
||||
// "Return Home: Sets DDRAM address to "00H" from AC and return cursor to its
|
||||
// original position if shifted."
|
||||
#define DISP_CMD_HOME 2 // Bit 0: don't care
|
||||
|
||||
// "Sets DD RAM address in address counter"
|
||||
#define DISP_CMD_DDADDR 128
|
||||
// Bits 0-7 are the address:
|
||||
// 00-0F are the first line
|
||||
// 40-4F are the second line
|
||||
|
||||
#endif
|
@ -196,6 +196,8 @@ void i2c_start_cond(void)
|
||||
while (READSCL() == 0)
|
||||
; // You can add a timeout to this loop to
|
||||
// recover from SCL being stuck low.
|
||||
// Repeated start setup time, minimum 4.7us
|
||||
I2CDELAY();
|
||||
}
|
||||
if (READSDA() == 0)
|
||||
ARBITRATION_LOST();
|
||||
@ -214,7 +216,9 @@ void i2c_stop_cond(void)
|
||||
/* Clock stretching */
|
||||
while (READSCL() == 0)
|
||||
; /* You should add timeout to this loop */
|
||||
/* SCL is high, set SDA from 0 to 1 */
|
||||
/* SCL is high. Respect I2C spec's minimum stop setup time of 4ms. */
|
||||
I2CDELAY();
|
||||
/* set SDA from 0 to 1 */
|
||||
if (READSDA() == 0)
|
||||
ARBITRATION_LOST();
|
||||
I2CDELAY();
|
||||
|
@ -1,5 +1,7 @@
|
||||
// Declarations for the low-level AVR32 I2C driver for eLua
|
||||
|
||||
#include "type.h" // for u32
|
||||
|
||||
u32 i2c_setup( u32 speed ); // speed is in Hz
|
||||
void i2c_start_cond( void );
|
||||
void i2c_stop_cond( void );
|
||||
|
392
src/platform/avr32/lcd.c
Normal file
392
src/platform/avr32/lcd.c
Normal file
@ -0,0 +1,392 @@
|
||||
// eLua module for Mizar32 LCD character display
|
||||
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "lrotable.h"
|
||||
#include "platform_conf.h"
|
||||
|
||||
#include "lcd.h"
|
||||
#include "i2c.h"
|
||||
|
||||
|
||||
// Since the LCD firmware currently only runs at up to 20kHz on the I2C bus,
|
||||
// we bracket all I2C packets to the LCD module with two functions
|
||||
// to be able to save, change and restore the I2C clock rate to what it was
|
||||
// before.
|
||||
|
||||
// Declarations to save/restore the I2C clock rate
|
||||
extern u32 i2c_delay;
|
||||
static u32 old_i2c_delay;
|
||||
|
||||
static void lcd_start()
|
||||
{
|
||||
old_i2c_delay = i2c_delay;
|
||||
i2c_delay = REQ_CPU_FREQ / LCD_BUS_FREQ / 2;
|
||||
}
|
||||
|
||||
static void lcd_stop()
|
||||
{
|
||||
i2c_delay = old_i2c_delay;
|
||||
}
|
||||
|
||||
|
||||
// Low-level functions to send LCD commands or data.
|
||||
// The command and data packets differ only in the slave address used,
|
||||
// so we coalesce them into a single function, generating smaller code.
|
||||
//
|
||||
// All three are designed to be used in a tail call:
|
||||
// return send_generic( data, len );
|
||||
|
||||
// Send a command or data packet.
|
||||
// "address" is LCD_CMD for LCD commands, LCD_DATA for LCD data.
|
||||
static int send_generic(char address, const char *data, int len)
|
||||
{
|
||||
while (len > 0) {
|
||||
int nbytes; // number of bytes sent in this I2C packet
|
||||
|
||||
lcd_start();
|
||||
i2c_start_cond();
|
||||
i2c_write_byte( address );
|
||||
// Mizar32 LCD module has a maximum of 31 bytes per data packet
|
||||
nbytes = 0;
|
||||
while ( len > 0 && nbytes < 31 ) {
|
||||
i2c_write_byte( *data++ );
|
||||
nbytes++; len--;
|
||||
}
|
||||
i2c_stop_cond();
|
||||
lcd_stop();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Send a single command byte
|
||||
static int send_command(const char command)
|
||||
{
|
||||
return send_generic(LCD_CMD, &command, 1);
|
||||
}
|
||||
|
||||
// Send multiple command bytes as one message
|
||||
static int send_commands(const char *commands, int len)
|
||||
{
|
||||
return send_generic(LCD_CMD, commands, len);
|
||||
}
|
||||
|
||||
// Send data bytes
|
||||
// This is used for printing data and for programming the user-defining chars
|
||||
static int send_data(const char *data, int len)
|
||||
{
|
||||
return send_generic(LCD_DATA, data, len);
|
||||
}
|
||||
|
||||
|
||||
// *** Lua module functions begin... ***
|
||||
|
||||
|
||||
// Turning the display on can only be achieved by simultaneously specifying the
|
||||
// cursor type, so we have to remember what type of cursor they last set.
|
||||
// Similarly, if they have turned the display off then set the cursor, this
|
||||
// shouldn-t turn the display on.
|
||||
|
||||
// Power-on setting is no cursor
|
||||
#define DEFAULT_CURSOR_TYPE LCD_CMD_CURSOR_NONE
|
||||
|
||||
static char cursor_type = DEFAULT_CURSOR_TYPE;
|
||||
static char display_is_off = 0; // Have they called display("off")?
|
||||
|
||||
|
||||
// Should we try to maintain the current cursor position across a definechar()?
|
||||
// Unfortunately we can't read the current cursor position, and definechar()
|
||||
// destroys it. The LCD controller does have a read-cursor-position primitive
|
||||
// but the current PIC firmware doesn't pass this on as an I2C read.2
|
||||
// So we have to track the cursor position. Yuk.
|
||||
// The only relief is that we don't have to track the display scrolling.
|
||||
// Adds 284 bytes of code to the executable.
|
||||
//
|
||||
// If, one day, we can read the LCD cursor position through the PIC firmware
|
||||
// we can remove all this stuff.
|
||||
#define KEEP_CURSOR_POSITION 1
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
// Where is the cursor in the character memory? Required ONLY to be able to
|
||||
// restore the cursor position when they define a character :-/
|
||||
static int current_row = 0; // 0 or 1
|
||||
static int current_column = 0; // 0-39 (though it over- and underflows)
|
||||
static int current_direction = 1; // left-to-right. -1 is right-to-left
|
||||
#endif
|
||||
|
||||
|
||||
// Lua: mizar32.disp.reset()
|
||||
// Ensure the display is in a known initial state
|
||||
static int lcd_reset( lua_State *L )
|
||||
{
|
||||
// Initialise the display to a known state
|
||||
static const char reset[] = {
|
||||
0 /* reset */
|
||||
};
|
||||
|
||||
// Set the static variables
|
||||
cursor_type = DEFAULT_CURSOR_TYPE;
|
||||
display_is_off = 0;
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = current_column = 0;
|
||||
current_direction = 1;
|
||||
#endif
|
||||
|
||||
return send_commands( reset, sizeof( reset ) );
|
||||
}
|
||||
|
||||
// "Entry mode" function.
|
||||
|
||||
// Lua: mizar32.disp.setup( shift_display, right-to-left )
|
||||
// Set right-to-left mode,
|
||||
static int lcd_setup( lua_State *L )
|
||||
{
|
||||
// lua_toboolean returns 0 or 1, and returns 0 if the parameter is absent
|
||||
unsigned shift_display = lua_toboolean( L, 1 ); // Default: move cursor
|
||||
unsigned right_to_left = lua_toboolean( L, 2 ); // Default: print left-to-right
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_direction = right_to_left ? -1 : 1;
|
||||
#endif
|
||||
|
||||
return send_command( LCD_CMD_ENTRYMODE + shift_display +
|
||||
(!right_to_left) * 2 );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.clear()
|
||||
// Clear the display, reset its shiftedness and put the cursor at 1,1
|
||||
static int lcd_clear( lua_State *L )
|
||||
{
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = current_column = 0;
|
||||
#endif
|
||||
return send_command( LCD_CMD_CLEAR );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.home()
|
||||
// Reset the display's shiftedness and put the cursor at 1,1
|
||||
static int lcd_home(lua_State *L)
|
||||
{
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = current_column = 0;
|
||||
#endif
|
||||
return send_command( LCD_CMD_HOME );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.goto( row, col )
|
||||
// Move the cursor to the specified row (1 or 2) and column (1-40)
|
||||
// in the character memory.
|
||||
static int lcd_goto(lua_State *L)
|
||||
{
|
||||
unsigned row = luaL_checkinteger( L, 1 );
|
||||
unsigned col = luaL_checkinteger( L, 2 );
|
||||
unsigned address;
|
||||
|
||||
if ( row < 1 || row > 2 || col < 1 || col > 40 )
|
||||
return luaL_error( L, "row/column must be 1-2 and 1-40" );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = row - 1;
|
||||
current_column = col - 1;
|
||||
#endif
|
||||
address = ( row - 1 ) * 0x40 + ( col - 1 ) ;
|
||||
return send_command( LCD_CMD_DDADDR + address );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.print( string )
|
||||
// Send data bytes to the LCD module.
|
||||
// Usually this will be a string of text or a list of character codes.
|
||||
// If they pass us integer values <0 or >255, we just use the bottom 8 bits.
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
// Adjust current cursor position by N printed characters.
|
||||
// Written for shortest code.
|
||||
static void current_print(int n)
|
||||
{
|
||||
current_column += current_direction * n;
|
||||
if (current_column < 0 || current_column >= 40) {
|
||||
current_row = ! current_row;
|
||||
current_column -= 40 * current_direction;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lcd_print(lua_State *L)
|
||||
{
|
||||
unsigned argc = lua_gettop( L ); // Number of parameters supplied
|
||||
int argn;
|
||||
|
||||
for ( argn = 1; argn <= argc; argn ++ )
|
||||
{
|
||||
switch (lua_type( L, argn ) )
|
||||
{
|
||||
case LUA_TNUMBER:
|
||||
{
|
||||
char byte = luaL_checkint( L, argn );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_print(1);
|
||||
#endif
|
||||
send_data(&byte, (size_t) 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case LUA_TSTRING:
|
||||
{
|
||||
size_t len; // Number of chars in string
|
||||
const char *str = luaL_checklstring( L, argn, &len );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_print(len);
|
||||
#endif
|
||||
send_data(str, len);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return luaL_typerror( L, argn, "integer or string" );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// "Display on/off control" functions
|
||||
|
||||
// Helper function to set a cursor type if the display is on,
|
||||
// or to remember which cursor they asked for, to be able to set it
|
||||
// when they turn the display on.
|
||||
static int set_cursor( char command_byte )
|
||||
{
|
||||
cursor_type = command_byte;
|
||||
|
||||
// Setting cursor type always turns the display on
|
||||
if (display_is_off)
|
||||
return 0;
|
||||
else
|
||||
return send_command( cursor_type );
|
||||
}
|
||||
|
||||
// Perform cursor operations, selected by a string parameter,
|
||||
// as recommended in the Lua Reference Manual, p.58: "luaL_checkoption()"
|
||||
static int lcd_cursor( lua_State *L )
|
||||
{
|
||||
static const char const *args[] =
|
||||
{ "none", "block", "line", "left", "right", NULL };
|
||||
|
||||
switch ( luaL_checkoption( L, 1, NULL, args ) )
|
||||
{
|
||||
case 0:
|
||||
return set_cursor( LCD_CMD_CURSOR_NONE );
|
||||
case 1:
|
||||
return set_cursor( LCD_CMD_CURSOR_BLOCK );
|
||||
case 2:
|
||||
return set_cursor( LCD_CMD_CURSOR_LINE );
|
||||
|
||||
case 3:
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
if (--current_column < 0) {
|
||||
current_row = !current_row;
|
||||
current_column = 39;
|
||||
}
|
||||
#endif
|
||||
return send_command( LCD_CMD_SHIFT_CURSOR_LEFT );
|
||||
|
||||
case 4:
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
if (++current_column >= 40) {
|
||||
current_row = !current_row;
|
||||
current_column = 0;
|
||||
}
|
||||
#endif
|
||||
return send_command( LCD_CMD_SHIFT_CURSOR_RIGHT );
|
||||
|
||||
default: return luaL_argerror( L, 1, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Perform display operations, selected by a string parameter.
|
||||
static int lcd_display( lua_State *L )
|
||||
{
|
||||
static const char const *args[] =
|
||||
{ "off", "on", "left", "right", NULL };
|
||||
|
||||
switch ( luaL_checkoption( L, 1, NULL, args ) )
|
||||
{
|
||||
case 0: display_is_off = 1;
|
||||
return send_command( LCD_CMD_DISPLAY_OFF );
|
||||
case 1: display_is_off = 0;
|
||||
return send_command( cursor_type ); // Turns display on
|
||||
case 2: return send_command( LCD_CMD_SHIFT_DISPLAY_LEFT );
|
||||
case 3: return send_command( LCD_CMD_SHIFT_DISPLAY_RIGHT );
|
||||
default: return luaL_argerror( L, 1, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.definechar( code, glyph )
|
||||
// code: 0-7
|
||||
// glyph: a table of up to 8 numbers with values 0-31.
|
||||
// If less than 8 are supplied, the bottom rows are blanked.
|
||||
// If more than 8 are supplied, the extra are ignored.
|
||||
|
||||
static int lcd_definechar( lua_State *L ) {
|
||||
int code; // The character code we are defining, 0-7
|
||||
size_t datalen; // The number of elements in the glyph table
|
||||
size_t line; // Which line of the char are we defining?
|
||||
char data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
int old_column = current_column, old_row = current_row;
|
||||
#endif
|
||||
|
||||
// First parameter: glyph code to define
|
||||
code = luaL_checkint( L, 1 );
|
||||
if( code < 0 || code > 7 )
|
||||
return luaL_error( L, "user-defined characters have codes 0-7");
|
||||
|
||||
// Second parameter: table of integer values to define the glyph
|
||||
luaL_checktype( L, 2, LUA_TTABLE );
|
||||
datalen = lua_objlen( L, 2 );
|
||||
// Check all parameters before starting the I2C command.
|
||||
if( datalen >= 8) datalen = 8; // Ignore extra parameters
|
||||
for( line = 0; line < datalen; line ++ )
|
||||
{
|
||||
int value;
|
||||
lua_rawgeti( L, 2, line + 1 );
|
||||
value = luaL_checkint( L, -1 );
|
||||
lua_pop( L, 1 );
|
||||
data[line] = value;
|
||||
}
|
||||
|
||||
send_command( LCD_CMD_CGADDR + code * 8 );
|
||||
send_data( data, sizeof(data) );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
// Move back to where we were
|
||||
current_row = old_row; current_column = old_column;
|
||||
return send_command( LCD_CMD_DDADDR + current_row * 0x40 + current_column );
|
||||
#else
|
||||
// Sadly, we cannot save and restore the current cursor position
|
||||
// so return to the home position.
|
||||
return send_command( LCD_CMD_DDADDR );
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
|
||||
// mizar32.disp.*() module function map
|
||||
const LUA_REG_TYPE lcd_map[] =
|
||||
{
|
||||
{ LSTRKEY( "reset" ), LFUNCVAL( lcd_reset ) },
|
||||
{ LSTRKEY( "setup" ), LFUNCVAL( lcd_setup ) },
|
||||
{ LSTRKEY( "clear" ), LFUNCVAL( lcd_clear ) },
|
||||
{ LSTRKEY( "home" ), LFUNCVAL( lcd_home ) },
|
||||
{ LSTRKEY( "goto" ), LFUNCVAL( lcd_goto ) },
|
||||
{ LSTRKEY( "print" ), LFUNCVAL( lcd_print ) },
|
||||
{ LSTRKEY( "definechar" ), LFUNCVAL( lcd_definechar ) },
|
||||
{ LSTRKEY( "cursor" ), LFUNCVAL( lcd_cursor ) },
|
||||
{ LSTRKEY( "display" ), LFUNCVAL( lcd_display ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
102
src/platform/avr32/lcd.h
Normal file
102
src/platform/avr32/lcd.h
Normal file
@ -0,0 +1,102 @@
|
||||
// Mizar32 LCD character display
|
||||
|
||||
#ifndef __LCD_H__
|
||||
#define __LCD_H__
|
||||
|
||||
// See the Ampire datasheet http://home.comet.bg/datasheets/LCD/AC-162B.pdf
|
||||
// and http://embeddedtutorial.com/2010/01/interfacing-lcd-with-8051/
|
||||
|
||||
// I2C bus frequency that the LCD display runs at.
|
||||
// It works up to 54kHz, with another window at 67 to 68kHz.
|
||||
// For reliable operation, we set it to 10% less than the highest "normal" speed.
|
||||
#define LCD_BUS_FREQ 50000
|
||||
|
||||
// I2C slave addresses for command bytes and data strings
|
||||
// Command address is followed by a dingle byte giving the command to perform
|
||||
// Data address is followed by multiple bytes of ASCII data to display
|
||||
// on the character display at the current cursor location.
|
||||
#define LCD_CMD 0x7C
|
||||
#define LCD_DATA 0x7E
|
||||
|
||||
// Command bytes
|
||||
|
||||
// "Clear display: Write "20H" to DDRAM and set DDRAM address to "00H" from AC"
|
||||
#define LCD_CMD_CLEAR 1
|
||||
|
||||
// "Return Home: Sets DDRAM address to "00H" from AC and return cursor to its
|
||||
// original position if shifted."
|
||||
#define LCD_CMD_HOME 2 // Bit 0: don't care
|
||||
|
||||
// "Assign cursor moving direction and enable the shift of entire display"
|
||||
#define LCD_CMD_ENTRYMODE 4
|
||||
#define LCD_CMD_ENTRYMODE_SHIFT 1 // 0: move cursor / 1: shift display
|
||||
#define LCD_CMD_ENTRYMODE_DIRECTION 2 // 0: move/shift left / 1: right
|
||||
// or, if you prefer...
|
||||
#define LCD_CMD_ENTRYMODE_MOVE_LEFT 4 // move cursor left when printing
|
||||
#define LCD_CMD_ENTRYMODE_SHIFT_LEFT 5 // shift display left when printing
|
||||
#define LCD_CMD_ENTRYMODE_MOVE_RIGHT 6 // move cursor right when printing
|
||||
#define LCD_CMD_ENTRYMODE_SHIFT_RIGHT 7 // shift display right when printing
|
||||
|
||||
// Command 8 uses bits 4,2,1 to set display on/off, underline cursor on/off
|
||||
// and blinking block on/off.
|
||||
#define LCD_CMD_DISPLAY_OFF 8
|
||||
#define LCD_CMD_CURSOR_NONE 12
|
||||
#define LCD_CMD_CURSOR_BLOCK 13
|
||||
#define LCD_CMD_CURSOR_LINE 14
|
||||
#define LCD_CMD_CURSOR_BOTH 15
|
||||
|
||||
// "Set cursor moving and display shift control bit, and the direction,
|
||||
// without changing of DDRAM data".
|
||||
//
|
||||
// Actually, this sets no bits at all. It just moves the cursor one place
|
||||
// left or right or shift the display contents one place left or right.
|
||||
//
|
||||
// Command 16 uses bits 8 and 4 to move the cursor one place left or right in
|
||||
// the character memory and on the display,
|
||||
// or to shift the displayed characters one place left or right.
|
||||
// Bit 8 is 0 to move the cursor, 1 to shift the display
|
||||
// Bit 4 is 0 to move the cursor or to shift the displayed characters left,
|
||||
// 1 to move the cursor or to shift the displayed characters right
|
||||
// When shifting the display left, the cursor also moves one place left in the
|
||||
// physical display, so remains over the same character as before.
|
||||
#define LCD_CMD_SHIFT 16
|
||||
#define LCD_CMD_SHIFT_LEFT 0
|
||||
#define LCD_CMD_SHIFT_RIGHT 4
|
||||
#define LCD_CMD_SHIFT_CURSOR 0
|
||||
#define LCD_CMD_SHIFT_DISPLAY 8
|
||||
// or, if you prefer...
|
||||
#define LCD_CMD_SHIFT_CURSOR_LEFT 16
|
||||
#define LCD_CMD_SHIFT_CURSOR_RIGHT 20
|
||||
#define LCD_CMD_SHIFT_DISPLAY_LEFT 24
|
||||
#define LCD_CMD_SHIFT_DISPLAY_RIGHT 28
|
||||
|
||||
// Command 32 uses bits 16, 8 and 4 to set
|
||||
// - interface data length (0 = 4-bit, 16 = 8-bit). Mizar32 uses 4-bit
|
||||
// - number of displayed lines (0 = one, 8 = two)
|
||||
// - display font type (0 = 5x8, 4 = 5x11).
|
||||
#define LCD_CMD_FUNCTION 32
|
||||
#define LCD_CMD_FUNCTION_DATABITS_4 0
|
||||
#define LCD_CMD_FUNCTION_DATABITS_8 16
|
||||
#define LCD_CMD_FUNCTION_LINES_1 0
|
||||
#define LCD_CMD_FUNCTION_LINES_2 8
|
||||
#define LCD_CMD_FUNCTION_FONT_5x8 0
|
||||
#define LCD_CMD_FUNCTION_FONT_5x11 4
|
||||
|
||||
// "Sets CG RAM address in address counter"
|
||||
// Sets an address in the user-defined character generator RAM.
|
||||
// The bottom 6 bits define which character to define as code(0-7) * 8.
|
||||
// Data is then sent to write values 0-31 into the CG RAM, which define a
|
||||
// character with one byte per row from top to bottom, and bits
|
||||
// 16, 8, 4, 2, 1 defining the row's pixels left to right.
|
||||
#define LCD_CMD_CGADDR 64
|
||||
|
||||
// "Sets DD RAM address in address counter"
|
||||
// Bits 0-7 are the address:
|
||||
// 00-0F are the first line
|
||||
// 40-4F are the second line
|
||||
// The location automatically wraps from the end of the first row to the
|
||||
// start of the second, the end of the second to the start of the first and,
|
||||
// when printing from right to left, vice versa.
|
||||
#define LCD_CMD_DDADDR 128
|
||||
|
||||
#endif
|
@ -41,15 +41,21 @@
|
||||
#include "pwm.h"
|
||||
#include "i2c.h"
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
|
||||
// UIP sys tick data
|
||||
// NOTE: when using virtual timers, SYSTICKHZ and VTMR_FREQ_HZ should have the
|
||||
// same value, as they're served by the same timer (the systick)
|
||||
#define SYSTICKHZ 4
|
||||
#if !defined( VTMR_NUM_TIMERS ) || VTMR_NUM_TIMERS == 0
|
||||
# error "On AVR32, UIP needs virtual timer support. Define VTMR_NUM_TIMERS > 0."
|
||||
#endif
|
||||
|
||||
#define SYSTICKHZ VTMR_FREQ_HZ
|
||||
#define SYSTICKMS (1000 / SYSTICKHZ)
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
static int eth_timer_fired;
|
||||
#endif
|
||||
|
||||
#endif // BUILD_UIP
|
||||
|
||||
// ****************************************************************************
|
||||
// Platform initialization
|
||||
@ -785,7 +791,7 @@ __attribute__((__interrupt__)) static void adc_int_handler()
|
||||
}
|
||||
|
||||
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency )
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -821,15 +827,27 @@ int platform_adc_start_sequence( )
|
||||
# error "NUM_PWM > AVR32_PWM_CHANNEL_LENGTH"
|
||||
#endif
|
||||
|
||||
#if NUM_PWM > 0
|
||||
|
||||
static const gpio_map_t pwm_pins =
|
||||
{
|
||||
{ AVR32_PWM_0_PIN, AVR32_PWM_0_FUNCTION },
|
||||
{ AVR32_PWM_1_PIN, AVR32_PWM_1_FUNCTION },
|
||||
{ AVR32_PWM_2_PIN, AVR32_PWM_2_FUNCTION },
|
||||
{ AVR32_PWM_3_PIN, AVR32_PWM_3_FUNCTION },
|
||||
{ AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PB27
|
||||
{ AVR32_PWM_5_1_PIN, AVR32_PWM_5_1_FUNCTION }, // PB28
|
||||
{ AVR32_PWM_6_PIN, AVR32_PWM_6_FUNCTION },
|
||||
#if ( BOARD == ATEVK1100 ) || ( BOARD == MIZAR32 )
|
||||
{ AVR32_PWM_0_PIN, AVR32_PWM_0_FUNCTION }, // PB19 - LED4
|
||||
{ AVR32_PWM_1_PIN, AVR32_PWM_1_FUNCTION }, // PB20 - LED5
|
||||
{ AVR32_PWM_2_PIN, AVR32_PWM_2_FUNCTION }, // PB21 - LED6
|
||||
{ AVR32_PWM_3_PIN, AVR32_PWM_3_FUNCTION }, // PB22 - LED7
|
||||
{ AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PB27 - LED0
|
||||
{ AVR32_PWM_5_1_PIN, AVR32_PWM_5_1_FUNCTION }, // PB28 - LED1
|
||||
{ AVR32_PWM_6_PIN, AVR32_PWM_6_FUNCTION }, // PB18 - LCD_C / GPIO50
|
||||
#elif BOARD == ATEVK1101
|
||||
{ AVR32_PWM_0_0_PIN, AVR32_PWM_0_0_FUNCTION }, // PA7 LED0
|
||||
{ AVR32_PWM_1_0_PIN, AVR32_PWM_1_0_FUNCTION }, // PA8 LED1
|
||||
{ AVR32_PWM_2_0_PIN, AVR32_PWM_2_0_FUNCTION }, // PA21 LED2
|
||||
{ AVR32_PWM_3_0_PIN, AVR32_PWM_3_0_FUNCTION }, // PA14 ? or _1 PA25
|
||||
{ AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PA28 - audio out
|
||||
{ AVR32_PWM_5_1_PIN, AVR32_PWM_5_1_FUNCTION }, // PB5: UART1-RTS & Nexus i/f EVTIn / _0 PA18=Xin0
|
||||
{ AVR32_PWM_6_0_PIN, AVR32_PWM_6_0_FUNCTION }, // PA22 - LED3 and audio out
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -928,7 +946,7 @@ static void find_clock_configuration( u32 frequency,
|
||||
#undef prescalers
|
||||
|
||||
|
||||
static u32 pwm_set_clock_freq( u32 freq )
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 freq )
|
||||
{
|
||||
unsigned pre, div;
|
||||
|
||||
@ -938,31 +956,23 @@ static u32 pwm_set_clock_freq( u32 freq )
|
||||
return pwm_get_clock_freq();
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data)
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
// Sanity check
|
||||
if (id < 0 || id >= NUM_PWM)
|
||||
return 0;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
return pwm_set_clock_freq( data );
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
return pwm_get_clock_freq();
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
pwm_channel_start( id );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
pwm_channel_stop( id );
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return pwm_get_clock_freq();
|
||||
}
|
||||
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
pwm_channel_start( id );
|
||||
}
|
||||
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
pwm_channel_stop( id );
|
||||
}
|
||||
|
||||
#endif // #if NUM_PWM > 0
|
||||
|
||||
// ****************************************************************************
|
||||
// I2C support
|
||||
|
||||
@ -1102,12 +1112,12 @@ u32 platform_eth_get_elapsed_time()
|
||||
#include "lrotable.h"
|
||||
#include "lrodefs.h"
|
||||
|
||||
extern const LUA_REG_TYPE disp_map[];
|
||||
extern const LUA_REG_TYPE lcd_map[];
|
||||
|
||||
const LUA_REG_TYPE platform_map[] =
|
||||
{
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
{ LSTRKEY( "disp" ), LROVAL( disp_map ) },
|
||||
{ LSTRKEY( "lcd" ), LROVAL( lcd_map ) },
|
||||
#endif
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
@ -1121,8 +1131,8 @@ LUALIB_API int luaopen_platform( lua_State *L )
|
||||
|
||||
// Setup the new tables inside platform table
|
||||
lua_newtable( L );
|
||||
luaL_register( L, NULL, disp_map );
|
||||
lua_setfield( L, -2, "disp" );
|
||||
luaL_register( L, NULL, lcd_map );
|
||||
lua_setfield( L, -2, "lcd" );
|
||||
|
||||
return 1;
|
||||
#endif // #if LUA_OPTIMIZE_MEMORY > 0
|
||||
|
@ -103,9 +103,3 @@ const LUA_REG_TYPE disp_map[] =
|
||||
{ LSTRKEY( "draw" ), LFUNCVAL( disp_imageDraw ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
LUALIB_API int luaopen_disp( lua_State *L )
|
||||
{
|
||||
LREGISTER( L, AUXLIB_DISP, disp_map );
|
||||
}
|
||||
|
||||
|
@ -624,8 +624,8 @@ static void pwms_init()
|
||||
MAP_SysCtlPWMClockSet( SYSCTL_PWMDIV_1 );
|
||||
}
|
||||
|
||||
// Helper function: return the PWM clock
|
||||
static u32 platform_pwm_get_clock()
|
||||
// Return the PWM clock
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
unsigned i;
|
||||
u32 clk;
|
||||
@ -637,8 +637,8 @@ static u32 platform_pwm_get_clock()
|
||||
return MAP_SysCtlClockGet() / pwm_div_data[ i ];
|
||||
}
|
||||
|
||||
// Helper function: set the PWM clock
|
||||
static u32 platform_pwm_set_clock( u32 clock )
|
||||
// Set the PWM clock
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
unsigned i, min_i;
|
||||
u32 sysclk;
|
||||
@ -653,7 +653,7 @@ static u32 platform_pwm_set_clock( u32 clock )
|
||||
|
||||
u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
{
|
||||
u32 pwmclk = platform_pwm_get_clock();
|
||||
u32 pwmclk = platform_pwm_get_clock( id );
|
||||
u32 period;
|
||||
|
||||
#if defined( FORLM3S9B92 ) || defined(FORLM3S9D92)
|
||||
@ -673,32 +673,16 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return pwmclk / period;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
u32 res = 0;
|
||||
MAP_PWMOutputState( PWM_BASE, 1 << id, true );
|
||||
MAP_PWMGenEnable( PWM_BASE, pwm_gens[ id >> 1 ] );
|
||||
}
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_pwm_get_clock();
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
MAP_PWMOutputState( PWM_BASE, 1 << id, true );
|
||||
MAP_PWMGenEnable( PWM_BASE, pwm_gens[ id >> 1 ] );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
MAP_PWMOutputState( PWM_BASE, 1 << id, false );
|
||||
MAP_PWMGenDisable( PWM_BASE, pwm_gens[ id >> 1 ] );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
MAP_PWMOutputState( PWM_BASE, 1 << id, false );
|
||||
MAP_PWMGenDisable( PWM_BASE, pwm_gens[ id >> 1 ] );
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
@ -818,12 +802,12 @@ static void adcs_init()
|
||||
adc_init_ch_state( id );
|
||||
|
||||
// Perform sequencer setup
|
||||
platform_adc_setclock( 0, 0 );
|
||||
platform_adc_set_clock( 0, 0 );
|
||||
MAP_ADCIntEnable( ADC_BASE, d->seq_id );
|
||||
MAP_IntEnable( adc_ints[ 0 ] ); // Enable sequencer 0 int
|
||||
}
|
||||
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency )
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
||||
|
@ -427,12 +427,12 @@ static void platform_setup_adcs()
|
||||
// Default enables ADC interrupt only on global, switch to per-channel
|
||||
ADC_IntConfig( LPC_ADC, ADC_ADGINTEN, DISABLE );
|
||||
|
||||
platform_adc_setclock( 0, 0 );
|
||||
platform_adc_set_clock( 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
// NOTE: On this platform, there is only one ADC, clock settings apply to the whole device
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency )
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
{
|
||||
TIM_TIMERCFG_Type TIM_ConfigStruct;
|
||||
TIM_MATCHCFG_Type TIM_MatchConfigStruct ;
|
||||
@ -538,13 +538,13 @@ int platform_adc_start_sequence()
|
||||
|
||||
|
||||
// Helper function: get timer clock
|
||||
static u32 platform_pwm_get_clock( unsigned id )
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
return CLKPWR_GetPCLK( CLKPWR_PCLKSEL_PWM1 ) / ( LPC_PWM1->PR + 1 );
|
||||
}
|
||||
|
||||
// Helper function: set timer clock
|
||||
static u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
PWM_TIMERCFG_Type PWMCfgDat;
|
||||
|
||||
@ -599,30 +599,14 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return platform_pwm_get_clock( id ) / divisor;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
u32 res = 0;
|
||||
PWM_Cmd(LPC_PWM1, ENABLE);
|
||||
}
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_START:
|
||||
PWM_Cmd(LPC_PWM1, ENABLE);
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
PWM_Cmd(LPC_PWM1, DISABLE);
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_pwm_get_clock( id );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
PWM_Cmd(LPC_PWM1, DISABLE);
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
|
@ -663,7 +663,7 @@ static void platform_setup_adcs()
|
||||
|
||||
|
||||
// NOTE: On this platform, there is only one ADC, clock settings apply to the whole device
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency )
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
||||
@ -799,8 +799,8 @@ enum
|
||||
PWM_ENABLE_6 = 1 << 14,
|
||||
};
|
||||
|
||||
// Helper function: get timer clock
|
||||
static u32 platform_pwm_get_clock( unsigned id )
|
||||
// Get timer clock
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
unsigned pwmid = id / 6;
|
||||
PREG PWMxPR = ( PREG )pwm_pr[ pwmid ];
|
||||
@ -808,8 +808,8 @@ static u32 platform_pwm_get_clock( unsigned id )
|
||||
return Fpclk / ( *PWMxPR + 1 );
|
||||
}
|
||||
|
||||
// Helper function: set timer clock
|
||||
static u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
// Set timer clock
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
u32 div = Fpclk / clock, prevtc;
|
||||
unsigned pwmid = id / 6;
|
||||
@ -860,34 +860,22 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return platform_pwm_get_clock( id ) / divisor;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
u32 res = 0;
|
||||
unsigned pwmid = id / 6;
|
||||
PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ];
|
||||
PREG PWMxPCR = ( PREG )pwm_pcr[ pwmid ];
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_START:
|
||||
*PWMxPCR = PWM_ENABLE_1 | PWM_ENABLE_2 | PWM_ENABLE_3 | PWM_ENABLE_4 | PWM_ENABLE_5 | PWM_ENABLE_6;
|
||||
*PWMxTCR = PWM_ENABLE | PWM_MODE;
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
*PWMxPCR = 0;
|
||||
*PWMxTCR = PWM_RESET;
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_pwm_get_clock( id );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
*PWMxPCR = PWM_ENABLE_1 | PWM_ENABLE_2 | PWM_ENABLE_3 | PWM_ENABLE_4 | PWM_ENABLE_5 | PWM_ENABLE_6;
|
||||
*PWMxTCR = PWM_ENABLE | PWM_MODE;
|
||||
}
|
||||
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
unsigned pwmid = id / 6;
|
||||
PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ];
|
||||
PREG PWMxPCR = ( PREG )pwm_pcr[ pwmid ];
|
||||
|
||||
*PWMxPCR = 0;
|
||||
*PWMxTCR = PWM_RESET;
|
||||
}
|
||||
|
@ -692,13 +692,15 @@ int platform_s_uart_set_flow_control( unsigned id, int type )
|
||||
// ****************************************************************************
|
||||
// Timers
|
||||
|
||||
u8 stm32_timer_int_periodic_flag[ NUM_PHYS_TIMER ];
|
||||
|
||||
// We leave out TIM6/TIM for now, as they are dedicated
|
||||
static TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 };
|
||||
const TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 };
|
||||
#define TIM_GET_PRESCALE( id ) ( ( id ) == 0 || ( id ) == 5 ? ( PCLK2_DIV ) : ( PCLK1_DIV ) )
|
||||
#define TIM_GET_BASE_CLK( id ) ( TIM_GET_PRESCALE( id ) == 1 ? ( HCLK / TIM_GET_PRESCALE( id ) ) : ( HCLK / ( TIM_GET_PRESCALE( id ) / 2 ) ) )
|
||||
#define TIM_STARTUP_CLOCK 50000
|
||||
|
||||
static u32 timer_set_clock( unsigned id, u32 clock );
|
||||
static u32 platform_timer_set_clock( unsigned id, u32 clock );
|
||||
|
||||
void SysTick_Handler( void )
|
||||
{
|
||||
@ -723,17 +725,17 @@ static void timers_init()
|
||||
|
||||
// Configure timers
|
||||
for( i = 0; i < NUM_TIMER; i ++ )
|
||||
timer_set_clock( i, TIM_STARTUP_CLOCK );
|
||||
platform_timer_set_clock( i, TIM_STARTUP_CLOCK );
|
||||
}
|
||||
|
||||
static u32 timer_get_clock( unsigned id )
|
||||
static u32 platform_timer_get_clock( unsigned id )
|
||||
{
|
||||
TIM_TypeDef* ptimer = timer[ id ];
|
||||
|
||||
return TIM_GET_BASE_CLK( id ) / ( TIM_GetPrescaler( ptimer ) + 1 );
|
||||
}
|
||||
|
||||
static u32 timer_set_clock( unsigned id, u32 clock )
|
||||
static u32 platform_timer_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_TypeDef *ptimer = timer[ id ];
|
||||
@ -756,7 +758,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
|
||||
volatile unsigned dummy;
|
||||
timer_data_type final;
|
||||
|
||||
final = ( ( u64 )delay_us * timer_get_clock( id ) ) / 1000000;
|
||||
final = ( ( u64 )delay_us * platform_timer_get_clock( id ) ) / 1000000;
|
||||
TIM_SetCounter( ptimer, 0 );
|
||||
for( dummy = 0; dummy < 200; dummy ++ );
|
||||
while( TIM_GetCounter( ptimer ) < final );
|
||||
@ -789,11 +791,11 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_SET_CLOCK:
|
||||
res = timer_set_clock( id, data );
|
||||
res = platform_timer_set_clock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_CLOCK:
|
||||
res = timer_get_clock( id );
|
||||
res = platform_timer_get_clock( id );
|
||||
break;
|
||||
|
||||
}
|
||||
@ -802,7 +804,54 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
|
||||
int platform_s_timer_set_match_int( unsigned id, u32 period_us, int type )
|
||||
{
|
||||
return PLATFORM_TIMER_INT_INVALID_ID;
|
||||
TIM_TypeDef* base = ( TIM_TypeDef* )timer[ id ];
|
||||
u32 period, prescaler, freq;
|
||||
timer_data_type final;
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
|
||||
if( period_us == 0 )
|
||||
{
|
||||
TIM_ITConfig( base, TIM_IT_CC1, DISABLE );
|
||||
base->CR1 = 0; // Why are we doing this?
|
||||
base->CR2 = 0;
|
||||
return PLATFORM_TIMER_INT_OK;
|
||||
}
|
||||
|
||||
period = ( ( u64 )TIM_GET_BASE_CLK( id ) * period_us ) / 1000000;
|
||||
|
||||
prescaler = ( period / 0x10000 ) + 1;
|
||||
period /= prescaler;
|
||||
|
||||
platform_timer_set_clock( id, TIM_GET_BASE_CLK( id ) / prescaler );
|
||||
freq = platform_timer_get_clock( id );
|
||||
final = ( ( u64 )period_us * freq ) / 1000000;
|
||||
|
||||
if( final == 0 )
|
||||
return PLATFORM_TIMER_INT_TOO_SHORT;
|
||||
if( final > 0xFFFF )
|
||||
return PLATFORM_TIMER_INT_TOO_LONG;
|
||||
|
||||
TIM_Cmd( base, DISABLE );
|
||||
|
||||
TIM_OCStructInit( &TIM_OCInitStructure );
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_Pulse = final;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
TIM_OC1Init( base, &TIM_OCInitStructure );
|
||||
|
||||
// Patch timer configuration to reload when period is reached
|
||||
TIM_SetAutoreload( base, final );
|
||||
|
||||
TIM_OC1PreloadConfig( base, TIM_OCPreload_Enable );
|
||||
|
||||
stm32_timer_int_periodic_flag[ id ] = type;
|
||||
|
||||
TIM_SetCounter( base, 0 );
|
||||
TIM_Cmd( base, ENABLE );
|
||||
//TIM_ITConfig( base, TIM_IT_CC1, ENABLE );
|
||||
|
||||
return PLATFORM_TIMER_INT_OK;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
@ -844,16 +893,17 @@ static void pwms_init()
|
||||
//
|
||||
}
|
||||
|
||||
// Helper function: return the PWM clock
|
||||
// NOTE: Can't find a function to query for the period set for the timer, therefore using the struct.
|
||||
// This may require adjustment if driver libraries are updated.
|
||||
static u32 platform_pwm_get_clock()
|
||||
// Return the PWM clock
|
||||
// NOTE: Can't find a function to query for the period set for the timer,
|
||||
// therefore using the struct.
|
||||
// This may require adjustment if driver libraries are updated.
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
return ( ( TIM_GET_BASE_CLK( PWM_TIMER_ID ) / ( TIM_GetPrescaler( PWM_TIMER_NAME ) + 1 ) ) / ( PWM_TIMER_NAME->ARR + 1 ) );
|
||||
}
|
||||
|
||||
// Helper function: set the PWM clock
|
||||
static u32 platform_pwm_set_clock( u32 clock )
|
||||
// Set the PWM clock
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_TypeDef* ptimer = PWM_TIMER_NAME;
|
||||
@ -872,7 +922,7 @@ static u32 platform_pwm_set_clock( u32 clock )
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;
|
||||
TIM_TimeBaseInit( ptimer, &TIM_TimeBaseStructure );
|
||||
|
||||
return platform_pwm_get_clock();
|
||||
return platform_pwm_get_clock( id );
|
||||
}
|
||||
|
||||
u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
@ -891,7 +941,7 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
clock = platform_pwm_set_clock( frequency );
|
||||
clock = platform_pwm_set_clock( id, frequency );
|
||||
TIM_ARRPreloadConfig( ptimer, ENABLE );
|
||||
|
||||
/* PWM Mode configuration */
|
||||
@ -931,30 +981,14 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return clock;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
u32 res = 0;
|
||||
PWM_TIMER_NAME->CCER |= ( ( u16 )1 << 4 * id );
|
||||
}
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_pwm_get_clock();
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
PWM_TIMER_NAME->CCER |= ( ( u16 )1 << 4 * id );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
PWM_TIMER_NAME->CCER &= ~( ( u16 )1 << 4 * id );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
PWM_TIMER_NAME->CCER &= ~( ( u16 )1 << 4 * id );
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
@ -1148,10 +1182,10 @@ static void adcs_init()
|
||||
DMA_Cmd( DMA1_Channel1, ENABLE );
|
||||
DMA_ITConfig( DMA1_Channel1, DMA1_IT_TC1 , ENABLE );
|
||||
|
||||
platform_adc_setclock( 0, 0 );
|
||||
platform_adc_set_clock( 0, 0 );
|
||||
}
|
||||
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency )
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef timer_base_struct;
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
@ -112,6 +112,7 @@
|
||||
#define NUM_SPI 2
|
||||
#define NUM_UART 5
|
||||
#define NUM_TIMER 5
|
||||
#define NUM_PHYS_TIMER 5
|
||||
#define NUM_PWM 4
|
||||
#define NUM_ADC 16
|
||||
#define NUM_CAN 1
|
||||
|
@ -9,6 +9,10 @@
|
||||
// Platform-specific headers
|
||||
#include "stm32f10x.h"
|
||||
|
||||
#ifndef VTMR_TIMER_ID
|
||||
#define VTMR_TIMER_ID ( -1 )
|
||||
#endif
|
||||
|
||||
// ****************************************************************************
|
||||
// Interrupt handlers
|
||||
|
||||
@ -128,6 +132,61 @@ void EXTI15_10_IRQHandler()
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Timer interrupt handlers
|
||||
|
||||
const TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 };
|
||||
extern u8 stm32_timer_int_periodic_flag[ NUM_PHYS_TIMER ];
|
||||
|
||||
static void tmr_int_handler( int id )
|
||||
{
|
||||
TIM_TypeDef *base = ( TIM_TypeDef* )timer[ id ];
|
||||
|
||||
if (TIM_GetITStatus( base, TIM_IT_CC1) != RESET)
|
||||
{
|
||||
TIM_ClearITPendingBit( base, TIM_IT_CC1 );
|
||||
|
||||
if( id == VTMR_TIMER_ID )
|
||||
cmn_virtual_timer_cb();
|
||||
else
|
||||
cmn_int_handler( INT_TMR_MATCH, id );
|
||||
|
||||
if( stm32_timer_int_periodic_flag[ id ] != PLATFORM_TIMER_INT_CYCLIC )
|
||||
TIM_ITConfig( base, TIM_IT_CC1, DISABLE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TIM1_CC_IRQHandler(void)
|
||||
{
|
||||
tmr_int_handler( 0 );
|
||||
}
|
||||
|
||||
void TIM2_IRQHandler(void)
|
||||
{
|
||||
tmr_int_handler( 1 );
|
||||
}
|
||||
|
||||
void TIM3_IRQHandler(void)
|
||||
{
|
||||
tmr_int_handler( 2 );
|
||||
}
|
||||
|
||||
void TIM4_IRQHandler(void)
|
||||
{
|
||||
tmr_int_handler( 3 );
|
||||
}
|
||||
|
||||
void TIM5_IRQHandler(void)
|
||||
{
|
||||
tmr_int_handler( 4 );
|
||||
}
|
||||
|
||||
void TIM8_CC_IRQHandler(void)
|
||||
{
|
||||
tmr_int_handler( 7 );
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// GPIO helper functions
|
||||
|
||||
@ -234,19 +293,30 @@ static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear )
|
||||
// ****************************************************************************
|
||||
// Interrupt: INT_TMR_MATCH
|
||||
|
||||
static int int_tmr_match_set_status( elua_int_resnum resnum, int status )
|
||||
{
|
||||
return PLATFORM_INT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
static int int_tmr_match_get_status( elua_int_resnum resnum )
|
||||
{
|
||||
return PLATFORM_INT_NOT_HANDLED;
|
||||
TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ];
|
||||
|
||||
return ( base->DIER & TIM_IT_CC1 ) != 0;
|
||||
}
|
||||
|
||||
static int int_tmr_match_set_status( elua_int_resnum resnum, int status )
|
||||
{
|
||||
int previous = int_tmr_match_get_status( resnum );
|
||||
TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ];
|
||||
|
||||
TIM_ITConfig( base, TIM_IT_CC1, status == PLATFORM_CPU_ENABLE ? ENABLE : DISABLE );
|
||||
return previous;
|
||||
}
|
||||
|
||||
static int int_tmr_match_get_flag( elua_int_resnum resnum, int clear )
|
||||
{
|
||||
return PLATFORM_INT_NOT_HANDLED;
|
||||
TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ];
|
||||
int status = TIM_GetFlagStatus( base, TIM_FLAG_CC1 );
|
||||
|
||||
if( clear )
|
||||
TIM_ClearFlag( base, TIM_FLAG_CC1 );
|
||||
return status;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
@ -287,6 +357,15 @@ static const u8 uart_irq_table[] = { USART1_IRQn, USART2_IRQn, USART3_IRQn, UART
|
||||
// EXTI IRQ table
|
||||
static const u8 exti_irq_table[] = { EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn };
|
||||
|
||||
// EXTI IRQ table
|
||||
#if defined( STM32F10X_LD )
|
||||
static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn };
|
||||
#elseif defined( STM32F10X_MD )
|
||||
static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn };
|
||||
#else
|
||||
static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn, TIM5_IRQn };
|
||||
#endif
|
||||
|
||||
void platform_int_init()
|
||||
{
|
||||
NVIC_InitTypeDef nvic_init_structure;
|
||||
@ -295,7 +374,8 @@ void platform_int_init()
|
||||
// Enable all USART interrupts in the NVIC
|
||||
nvic_init_structure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||
nvic_init_structure.NVIC_IRQChannelSubPriority = 0;
|
||||
nvic_init_structure.NVIC_IRQChannelCmd = ENABLE;
|
||||
nvic_init_structure.NVIC_IRQChannelCmd = ENABLE;
|
||||
|
||||
for( i = 0; i < sizeof( uart_irq_table ) / sizeof( u8 ); i ++ )
|
||||
{
|
||||
nvic_init_structure.NVIC_IRQChannel = uart_irq_table[ i ];
|
||||
@ -309,6 +389,15 @@ void platform_int_init()
|
||||
NVIC_Init( &nvic_init_structure );
|
||||
}
|
||||
|
||||
#ifdef INT_TMR_MATCH
|
||||
for( i = 0; i < sizeof( timer_irq_table ) / sizeof( u8 ); i ++ )
|
||||
{
|
||||
nvic_init_structure.NVIC_IRQChannel = timer_irq_table[ i ];
|
||||
nvic_init_structure.NVIC_IRQChannelSubPriority = 1;
|
||||
NVIC_Init( &nvic_init_structure );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
|
@ -319,31 +319,26 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return pwmclk / period;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
u32 res = 0;
|
||||
TIM_TypeDef *ptimer = ( TIM_TypeDef* )tim_periph[ id + 1 ];
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_timer_set_clock( id + 1, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_timer_get_clock( id + 1 );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
TIM_CounterConfig( ptimer, TIM_START );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
TIM_CounterConfig( ptimer, TIM_STOP );
|
||||
platform_pio_op( pwm_ports[ id ], pwm_pins[ id ], PLATFORM_IO_PIN_DIR_INPUT );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
return platform_timer_set_clock( id + 1, clock );
|
||||
}
|
||||
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
return platform_timer_get_clock( id + 1 );
|
||||
}
|
||||
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
TIM_TypeDef *ptimer = ( TIM_TypeDef* )tim_periph[ id + 1 ];
|
||||
|
||||
TIM_CounterConfig( ptimer, TIM_START );
|
||||
}
|
||||
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
TIM_TypeDef *ptimer = ( TIM_TypeDef* )tim_periph[ id + 1 ];
|
||||
|
||||
platform_pio_op( pwm_ports[ id ], pwm_pins[ id ], PLATFORM_IO_PIN_DIR_INPUT );
|
||||
}
|
||||
|
@ -524,12 +524,12 @@ static void platform_setup_adcs()
|
||||
|
||||
ADC_ITConfig(ADC_IT_ECV, ENABLE);
|
||||
|
||||
platform_adc_setclock( 0, 0 );
|
||||
platform_adc_set_clock( 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
// NOTE: On this platform, there is only one ADC, clock settings apply to the whole device
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency )
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
||||
@ -658,7 +658,7 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return base / div;
|
||||
}
|
||||
|
||||
static u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
|
||||
u32 base = ( SCU_GetPCLKFreqValue() * 1000 );
|
||||
@ -668,31 +668,25 @@ static u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
return base / div;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
u32 res = 0;
|
||||
TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_START:
|
||||
TIM_CounterCmd( p_timer, TIM_START );
|
||||
break;
|
||||
return ( SCU_GetPCLKFreqValue() * 1000 ) / ( TIM_GetPrescalerValue( p_timer ) + 1 );
|
||||
}
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
TIM_CounterCmd( p_timer, TIM_STOP );
|
||||
break;
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
|
||||
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( id, data );
|
||||
break;
|
||||
TIM_CounterCmd( p_timer, TIM_START );
|
||||
}
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = ( SCU_GetPCLKFreqValue() * 1000 ) / ( TIM_GetPrescalerValue( p_timer ) + 1 );
|
||||
break;
|
||||
}
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
|
||||
|
||||
return res;
|
||||
TIM_CounterCmd( p_timer, TIM_STOP );
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
|
@ -71,22 +71,3 @@ const LUA_REG_TYPE str9_pio_map[] =
|
||||
{ LSTRKEY( "setpin" ), LFUNCVAL( setpin) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
LUALIB_API int luaopen_disp( lua_State *L )
|
||||
{
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
return 0;
|
||||
#else
|
||||
luaL_register( L, PS_LIB_TABLE_NAME, str9_pio_map );
|
||||
MOD_REG_NUMBER( L, "INPUT", GPIO_DIR_INPUT );
|
||||
MOD_REG_NUMBER( L, "OUTPUT", GPIO_DIR_OUTPUT );
|
||||
MOD_REG_NUMBER( L, "ALT_INPUT", GPIO_ALT_INPUT );
|
||||
MOD_REG_NUMBER( L, "ALT_OUTPUT1", GPIO_ALT_OUTPUT1 );
|
||||
MOD_REG_NUMBER( L, "ALT_OUTPUT2", GPIO_ALT_OUTPUT2 );
|
||||
MOD_REG_NUMBER( L, "ALT_OUTPUT3", GPIO_ALT_OUTPUT3 );
|
||||
MOD_REG_NUMBER( L, "OUTPUT_PUSHPULL", GPIO_OUTPUT_PP );
|
||||
MOD_REG_NUMBER( L, "OUTPUT_OC", GPIO_OUTPUT_OC );
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -276,17 +276,17 @@ PT_THREAD(handle_dhcp(void))
|
||||
s.timer_init = platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_START, 0 );
|
||||
PT_YIELD_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_us( ELUA_DHCP_TIMER_ID, s.timer_init, platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_READ, 0 ) ) >= s.ticks );
|
||||
if(uip_newdata() && parse_msg() == DHCPOFFER) {
|
||||
uip_flags &= ~UIP_NEWDATA;
|
||||
uip_flags &= ~UIP_NEWDATA;
|
||||
s.state = STATE_OFFER_RECEIVED;
|
||||
break;
|
||||
}
|
||||
uip_flags &= ~UIP_NEWDATA;
|
||||
uip_flags &= ~UIP_NEWDATA;
|
||||
if(s.ticks < CLOCK_SECOND * 60) {
|
||||
s.ticks *= 2;
|
||||
} else {
|
||||
s.ipaddr[0] = 0;
|
||||
goto dhcp_failed;
|
||||
}
|
||||
s.ipaddr[0] = 0;
|
||||
goto dhcp_failed;
|
||||
}
|
||||
} while(s.state != STATE_OFFER_RECEIVED);
|
||||
|
||||
s.ticks = CLOCK_SECOND;
|
||||
@ -297,7 +297,7 @@ PT_THREAD(handle_dhcp(void))
|
||||
PT_YIELD_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_us( ELUA_DHCP_TIMER_ID, s.timer_init, platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_READ, 0 ) ) >= s.ticks );
|
||||
|
||||
if(uip_newdata() && parse_msg() == DHCPACK) {
|
||||
uip_flags &= ~UIP_NEWDATA;
|
||||
uip_flags &= ~UIP_NEWDATA;
|
||||
s.state = STATE_CONFIG_RECEIVED;
|
||||
break;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@
|
||||
*/
|
||||
|
||||
#ifndef __LC_SWITCH_H__
|
||||
#define __LC_SWTICH_H__
|
||||
#define __LC_SWITCH_H__
|
||||
|
||||
/* WARNING! lc implementation using switch() does not work if an
|
||||
LC_SET() is done within another switch() statement! */
|
||||
|
@ -76,7 +76,7 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
buf_setup(struct psock_buf *buf,
|
||||
u8_t *bufptr, u16_t bufsize)
|
||||
u8_t *bufptr, u16_t bufsize)
|
||||
{
|
||||
buf->ptr = bufptr;
|
||||
buf->left = bufsize;
|
||||
@ -84,7 +84,7 @@ buf_setup(struct psock_buf *buf,
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static u8_t
|
||||
buf_bufdata(struct psock_buf *buf, u16_t len,
|
||||
u8_t **dataptr, u16_t *datalen)
|
||||
u8_t **dataptr, u16_t *datalen)
|
||||
{
|
||||
if(*datalen < buf->left) {
|
||||
memcpy(buf->ptr, *dataptr, *datalen);
|
||||
@ -112,7 +112,7 @@ buf_bufdata(struct psock_buf *buf, u16_t len,
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static u8_t
|
||||
buf_bufto(register struct psock_buf *buf, u8_t endmarker,
|
||||
register u8_t **dataptr, register u16_t *datalen)
|
||||
register u8_t **dataptr, register u16_t *datalen)
|
||||
{
|
||||
u8_t c;
|
||||
while(buf->left > 0 && *datalen > 0) {
|
||||
@ -177,7 +177,7 @@ data_acked(register struct psock *s)
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PT_THREAD(psock_send(register struct psock *s, const char *buf,
|
||||
unsigned int len))
|
||||
unsigned int len))
|
||||
{
|
||||
PT_BEGIN(&s->psockpt);
|
||||
|
||||
@ -188,7 +188,7 @@ PT_THREAD(psock_send(register struct psock *s, const char *buf,
|
||||
|
||||
/* Save the length of and a pointer to the data that is to be
|
||||
sent. */
|
||||
s->sendptr = buf;
|
||||
s->sendptr = (u8_t *)buf;
|
||||
s->sendlen = len;
|
||||
|
||||
s->state = STATE_NONE;
|
||||
@ -216,7 +216,7 @@ PT_THREAD(psock_send(register struct psock *s, const char *buf,
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PT_THREAD(psock_generator_send(register struct psock *s,
|
||||
unsigned short (*generate)(void *), void *arg))
|
||||
unsigned short (*generate)(void *), void *arg))
|
||||
{
|
||||
PT_BEGIN(&s->psockpt);
|
||||
|
||||
@ -276,7 +276,7 @@ PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
|
||||
{
|
||||
PT_BEGIN(&psock->psockpt);
|
||||
|
||||
buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
|
||||
buf_setup(&psock->buf, (u8_t *)psock->bufptr, psock->bufsize);
|
||||
|
||||
/* XXX: Should add buf_checkmarker() before do{} loop, if
|
||||
incoming data has been handled while waiting for a write. */
|
||||
@ -289,8 +289,8 @@ PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
|
||||
psock->readlen = uip_datalen();
|
||||
}
|
||||
} while((buf_bufto(&psock->buf, c,
|
||||
&psock->readptr,
|
||||
&psock->readlen) & BUF_FOUND) == 0);
|
||||
&psock->readptr,
|
||||
&psock->readlen) & BUF_FOUND) == 0);
|
||||
|
||||
if(psock_datalen(psock) == 0) {
|
||||
psock->state = STATE_NONE;
|
||||
@ -303,7 +303,7 @@ PT_THREAD(psock_readbuf(register struct psock *psock))
|
||||
{
|
||||
PT_BEGIN(&psock->psockpt);
|
||||
|
||||
buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
|
||||
buf_setup(&psock->buf, (u8_t *)psock->bufptr, psock->bufsize);
|
||||
|
||||
/* XXX: Should add buf_checkmarker() before do{} loop, if
|
||||
incoming data has been handled while waiting for a write. */
|
||||
@ -317,8 +317,8 @@ PT_THREAD(psock_readbuf(register struct psock *psock))
|
||||
psock->readlen = uip_datalen();
|
||||
}
|
||||
} while(buf_bufdata(&psock->buf, psock->bufsize,
|
||||
&psock->readptr,
|
||||
&psock->readlen) != BUF_FULL);
|
||||
&psock->readptr,
|
||||
&psock->readlen) != BUF_FULL);
|
||||
|
||||
if(psock_datalen(psock) == 0) {
|
||||
psock->state = STATE_NONE;
|
||||
@ -334,7 +334,7 @@ psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
|
||||
psock->readlen = 0;
|
||||
psock->bufptr = buffer;
|
||||
psock->bufsize = buffersize;
|
||||
buf_setup(&psock->buf, buffer, buffersize);
|
||||
buf_setup(&psock->buf, (u8_t *)buffer, buffersize);
|
||||
PT_INIT(&psock->pt);
|
||||
PT_INIT(&psock->psockpt);
|
||||
}
|
||||
|
@ -105,19 +105,19 @@ struct psock_buf {
|
||||
*/
|
||||
struct psock {
|
||||
struct pt pt, psockpt; /* Protothreads - one that's using the psock
|
||||
functions, and one that runs inside the
|
||||
psock functions. */
|
||||
functions, and one that runs inside the
|
||||
psock functions. */
|
||||
const u8_t *sendptr; /* Pointer to the next data to be sent. */
|
||||
u8_t *readptr; /* Pointer to the next data to be read. */
|
||||
|
||||
char *bufptr; /* Pointer to the buffer used for buffering
|
||||
incoming data. */
|
||||
incoming data. */
|
||||
|
||||
u16_t sendlen; /* The number of bytes left to be sent. */
|
||||
u16_t readlen; /* The number of bytes left to be read. */
|
||||
|
||||
struct psock_buf buf; /* The structure holding the state of the
|
||||
input buffer. */
|
||||
input buffer. */
|
||||
unsigned int bufsize; /* The size of the input buffer. */
|
||||
|
||||
unsigned char state; /* The state of the protosocket. */
|
||||
@ -175,7 +175,7 @@ PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len));
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PSOCK_SEND(psock, data, datalen) \
|
||||
#define PSOCK_SEND(psock, data, datalen) \
|
||||
PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen))
|
||||
|
||||
/**
|
||||
@ -188,11 +188,11 @@ PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len));
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PSOCK_SEND_STR(psock, str) \
|
||||
#define PSOCK_SEND_STR(psock, str) \
|
||||
PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str)))
|
||||
|
||||
PT_THREAD(psock_generator_send(struct psock *psock,
|
||||
unsigned short (*f)(void *), void *arg));
|
||||
unsigned short (*f)(void *), void *arg));
|
||||
|
||||
/**
|
||||
* \brief Generate data with a function and send it
|
||||
@ -216,9 +216,9 @@ PT_THREAD(psock_generator_send(struct psock *psock,
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PSOCK_GENERATOR_SEND(psock, generator, arg) \
|
||||
PT_WAIT_THREAD(&((psock)->pt), \
|
||||
psock_generator_send(psock, generator, arg))
|
||||
#define PSOCK_GENERATOR_SEND(psock, generator, arg) \
|
||||
PT_WAIT_THREAD(&((psock)->pt), \
|
||||
psock_generator_send(psock, generator, arg))
|
||||
|
||||
|
||||
/**
|
||||
@ -247,7 +247,7 @@ PT_THREAD(psock_readbuf(struct psock *psock));
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PSOCK_READBUF(psock) \
|
||||
#define PSOCK_READBUF(psock) \
|
||||
PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock))
|
||||
|
||||
PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
|
||||
@ -265,7 +265,7 @@ PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PSOCK_READTO(psock, c) \
|
||||
#define PSOCK_READTO(psock, c) \
|
||||
PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c))
|
||||
|
||||
/**
|
||||
@ -305,10 +305,10 @@ u16_t psock_datalen(struct psock *psock);
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PSOCK_CLOSE_EXIT(psock) \
|
||||
do { \
|
||||
PSOCK_CLOSE(psock); \
|
||||
PSOCK_EXIT(psock); \
|
||||
#define PSOCK_CLOSE_EXIT(psock) \
|
||||
do { \
|
||||
PSOCK_CLOSE(psock); \
|
||||
PSOCK_EXIT(psock); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
|
64
src/uip/pt.h
64
src/uip/pt.h
@ -145,12 +145,12 @@ struct pt {
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PT_WAIT_UNTIL(pt, condition) \
|
||||
do { \
|
||||
LC_SET((pt)->lc); \
|
||||
if(!(condition)) { \
|
||||
return PT_WAITING; \
|
||||
} \
|
||||
#define PT_WAIT_UNTIL(pt, condition) \
|
||||
do { \
|
||||
LC_SET((pt)->lc); \
|
||||
if(!(condition)) { \
|
||||
return PT_WAITING; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
@ -203,10 +203,10 @@ struct pt {
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PT_SPAWN(pt, child, thread) \
|
||||
do { \
|
||||
PT_INIT((child)); \
|
||||
PT_WAIT_THREAD((pt), (thread)); \
|
||||
#define PT_SPAWN(pt, child, thread) \
|
||||
do { \
|
||||
PT_INIT((child)); \
|
||||
PT_WAIT_THREAD((pt), (thread)); \
|
||||
} while(0)
|
||||
|
||||
/** @} */
|
||||
@ -226,10 +226,10 @@ struct pt {
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PT_RESTART(pt) \
|
||||
do { \
|
||||
PT_INIT(pt); \
|
||||
return PT_WAITING; \
|
||||
#define PT_RESTART(pt) \
|
||||
do { \
|
||||
PT_INIT(pt); \
|
||||
return PT_WAITING; \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
@ -243,10 +243,10 @@ struct pt {
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PT_EXIT(pt) \
|
||||
do { \
|
||||
PT_INIT(pt); \
|
||||
return PT_EXITED; \
|
||||
#define PT_EXIT(pt) \
|
||||
do { \
|
||||
PT_INIT(pt); \
|
||||
return PT_EXITED; \
|
||||
} while(0)
|
||||
|
||||
/** @} */
|
||||
@ -287,13 +287,13 @@ struct pt {
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PT_YIELD(pt) \
|
||||
do { \
|
||||
PT_YIELD_FLAG = 0; \
|
||||
LC_SET((pt)->lc); \
|
||||
if(PT_YIELD_FLAG == 0) { \
|
||||
return PT_YIELDED; \
|
||||
} \
|
||||
#define PT_YIELD(pt) \
|
||||
do { \
|
||||
PT_YIELD_FLAG = 0; \
|
||||
LC_SET((pt)->lc); \
|
||||
if(PT_YIELD_FLAG == 0) { \
|
||||
return PT_YIELDED; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
@ -307,13 +307,13 @@ struct pt {
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PT_YIELD_UNTIL(pt, cond) \
|
||||
do { \
|
||||
PT_YIELD_FLAG = 0; \
|
||||
LC_SET((pt)->lc); \
|
||||
if((PT_YIELD_FLAG == 0) || !(cond)) { \
|
||||
return PT_YIELDED; \
|
||||
} \
|
||||
#define PT_YIELD_UNTIL(pt, cond) \
|
||||
do { \
|
||||
PT_YIELD_FLAG = 0; \
|
||||
LC_SET((pt)->lc); \
|
||||
if((PT_YIELD_FLAG == 0) || !(cond)) { \
|
||||
return PT_YIELDED; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/** @} */
|
||||
|
108
src/uip/resolv.c
108
src/uip/resolv.c
@ -181,23 +181,23 @@ check_entries(void)
|
||||
if(namemapptr->state == STATE_NEW ||
|
||||
namemapptr->state == STATE_ASKING) {
|
||||
if(namemapptr->state == STATE_ASKING) {
|
||||
if(--namemapptr->tmr == 0) {
|
||||
if(++namemapptr->retries == MAX_RETRIES) {
|
||||
namemapptr->state = STATE_ERROR;
|
||||
resolv_found(namemapptr->name, NULL);
|
||||
continue;
|
||||
}
|
||||
namemapptr->tmr = namemapptr->retries;
|
||||
} else {
|
||||
/* printf("Timer %d\n", namemapptr->tmr);*/
|
||||
/* Its timer has not run out, so we move on to next
|
||||
entry. */
|
||||
continue;
|
||||
}
|
||||
if(--namemapptr->tmr == 0) {
|
||||
if(++namemapptr->retries == MAX_RETRIES) {
|
||||
namemapptr->state = STATE_ERROR;
|
||||
resolv_found(namemapptr->name, NULL);
|
||||
continue;
|
||||
}
|
||||
namemapptr->tmr = namemapptr->retries;
|
||||
} else {
|
||||
/* printf("Timer %d\n", namemapptr->tmr);*/
|
||||
/* Its timer has not run out, so we move on to next
|
||||
entry. */
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
namemapptr->state = STATE_ASKING;
|
||||
namemapptr->tmr = 1;
|
||||
namemapptr->retries = 0;
|
||||
namemapptr->state = STATE_ASKING;
|
||||
namemapptr->tmr = 1;
|
||||
namemapptr->retries = 0;
|
||||
}
|
||||
hdr = (struct dns_hdr *)uip_appdata;
|
||||
memset(hdr, 0, sizeof(struct dns_hdr));
|
||||
@ -209,20 +209,20 @@ check_entries(void)
|
||||
--nameptr;
|
||||
/* Convert hostname into suitable query format. */
|
||||
do {
|
||||
++nameptr;
|
||||
nptr = query;
|
||||
++query;
|
||||
for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) {
|
||||
*query = *nameptr;
|
||||
++query;
|
||||
++n;
|
||||
}
|
||||
*nptr = n;
|
||||
++nameptr;
|
||||
nptr = query;
|
||||
++query;
|
||||
for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) {
|
||||
*query = *nameptr;
|
||||
++query;
|
||||
++n;
|
||||
}
|
||||
*nptr = n;
|
||||
} while(*nameptr != 0);
|
||||
{
|
||||
static unsigned char endquery[] =
|
||||
{0,0,1,0,1};
|
||||
memcpy(query, endquery, 5);
|
||||
static unsigned char endquery[] =
|
||||
{0,0,1,0,1};
|
||||
memcpy(query, endquery, 5);
|
||||
}
|
||||
uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata));
|
||||
break;
|
||||
@ -237,7 +237,7 @@ check_entries(void)
|
||||
static void
|
||||
newdata(void)
|
||||
{
|
||||
char *nameptr;
|
||||
unsigned char *nameptr;
|
||||
struct dns_answer *ans;
|
||||
struct dns_hdr *hdr;
|
||||
static u8_t nquestions, nanswers;
|
||||
@ -281,44 +281,44 @@ newdata(void)
|
||||
/* Skip the name in the question. XXX: This should really be
|
||||
checked agains the name in the question, to be sure that they
|
||||
match. */
|
||||
nameptr = parse_name((char *)uip_appdata + 12) + 4;
|
||||
nameptr = parse_name((unsigned char *)uip_appdata + 12) + 4;
|
||||
|
||||
while(nanswers > 0) {
|
||||
/* The first byte in the answer resource record determines if it
|
||||
is a compressed record or a normal one. */
|
||||
is a compressed record or a normal one. */
|
||||
if(*nameptr & 0xc0) {
|
||||
/* Compressed name. */
|
||||
nameptr +=2;
|
||||
/* printf("Compressed anwser\n");*/
|
||||
/* Compressed name. */
|
||||
nameptr +=2;
|
||||
/* printf("Compressed anwser\n");*/
|
||||
} else {
|
||||
/* Not compressed name. */
|
||||
nameptr = parse_name((char *)nameptr);
|
||||
/* Not compressed name. */
|
||||
nameptr = parse_name(nameptr);
|
||||
}
|
||||
|
||||
ans = (struct dns_answer *)nameptr;
|
||||
/* printf("Answer: type %x, class %x, ttl %x, length %x\n",
|
||||
htons(ans->type), htons(ans->class), (htons(ans->ttl[0])
|
||||
<< 16) | htons(ans->ttl[1]), htons(ans->len));*/
|
||||
htons(ans->type), htons(ans->class), (htons(ans->ttl[0])
|
||||
<< 16) | htons(ans->ttl[1]), htons(ans->len));*/
|
||||
|
||||
/* Check for IP address type and Internet class. Others are
|
||||
discarded. */
|
||||
discarded. */
|
||||
if(ans->type == HTONS(1) &&
|
||||
ans->class == HTONS(1) &&
|
||||
ans->len == HTONS(4)) {
|
||||
/* printf("IP address %d.%d.%d.%d\n",
|
||||
htons(ans->ipaddr[0]) >> 8,
|
||||
htons(ans->ipaddr[0]) & 0xff,
|
||||
htons(ans->ipaddr[1]) >> 8,
|
||||
htons(ans->ipaddr[1]) & 0xff);*/
|
||||
/* XXX: we should really check that this IP address is the one
|
||||
we want. */
|
||||
namemapptr->ipaddr[0] = ans->ipaddr[0];
|
||||
namemapptr->ipaddr[1] = ans->ipaddr[1];
|
||||
|
||||
resolv_found(namemapptr->name, namemapptr->ipaddr);
|
||||
return;
|
||||
ans->class == HTONS(1) &&
|
||||
ans->len == HTONS(4)) {
|
||||
/* printf("IP address %d.%d.%d.%d\n",
|
||||
htons(ans->ipaddr[0]) >> 8,
|
||||
htons(ans->ipaddr[0]) & 0xff,
|
||||
htons(ans->ipaddr[1]) >> 8,
|
||||
htons(ans->ipaddr[1]) & 0xff);*/
|
||||
/* XXX: we should really check that this IP address is the one
|
||||
we want. */
|
||||
namemapptr->ipaddr[0] = ans->ipaddr[0];
|
||||
namemapptr->ipaddr[1] = ans->ipaddr[1];
|
||||
|
||||
resolv_found(namemapptr->name, namemapptr->ipaddr);
|
||||
return;
|
||||
} else {
|
||||
nameptr = nameptr + 10 + htons(ans->len);
|
||||
nameptr = nameptr + 10 + htons(ans->len);
|
||||
}
|
||||
--nanswers;
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ find_netif(void)
|
||||
/* Walk through every network interface to check for a match. */
|
||||
for(netif = netifs; netif != NULL; netif = netif->next) {
|
||||
if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
|
||||
netif->netmask)) {
|
||||
netif->netmask)) {
|
||||
/* If there was a match, we break the loop. */
|
||||
return netif;
|
||||
}
|
||||
@ -385,8 +385,8 @@ uip_fw_output(void)
|
||||
|
||||
netif = find_netif();
|
||||
/* printf("uip_fw_output: netif %p ->output %p len %d\n", netif,
|
||||
netif->output,
|
||||
uip_len);*/
|
||||
netif->output,
|
||||
uip_len);*/
|
||||
|
||||
if(netif == NULL) {
|
||||
return UIP_FW_NOROUTE;
|
||||
|
@ -53,12 +53,12 @@
|
||||
*/
|
||||
struct uip_fw_netif {
|
||||
struct uip_fw_netif *next; /**< Pointer to the next interface when
|
||||
linked in a list. */
|
||||
linked in a list. */
|
||||
u16_t ipaddr[2]; /**< The IP address of this interface. */
|
||||
u16_t netmask[2]; /**< The netmask of the interface. */
|
||||
u8_t (* output)(void);
|
||||
/**< A pointer to the function that
|
||||
sends a packet. */
|
||||
sends a packet. */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -79,8 +79,8 @@ struct uip_fw_netif {
|
||||
*/
|
||||
#define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \
|
||||
NULL, \
|
||||
{HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \
|
||||
{HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \
|
||||
{HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \
|
||||
{HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \
|
||||
outputfunc
|
||||
|
||||
/**
|
||||
|
@ -91,8 +91,8 @@ uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr)
|
||||
u8_t oldest_time;
|
||||
|
||||
/*printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
|
||||
addr->addr.addr[4], addr->addr.addr[5]);*/
|
||||
addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
|
||||
addr->addr.addr[4], addr->addr.addr[5]);*/
|
||||
|
||||
/* Find the first unused entry or the oldest used entry. */
|
||||
oldest_time = 0;
|
||||
@ -151,8 +151,8 @@ uip_neighbor_lookup(uip_ipaddr_t ipaddr)
|
||||
e = find_entry(ipaddr);
|
||||
if(e != NULL) {
|
||||
/* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3],
|
||||
e->addr.addr.addr[4], e->addr.addr.addr[5]);*/
|
||||
e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3],
|
||||
e->addr.addr.addr[4], e->addr.addr.addr[5]);*/
|
||||
|
||||
return &e->addr;
|
||||
}
|
||||
|
548
src/uip/uip.c
548
src/uip/uip.c
@ -129,52 +129,51 @@ static const uip_ipaddr_t all_zeroes_addr =
|
||||
|
||||
#if UIP_FIXEDETHADDR
|
||||
const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
|
||||
UIP_ETHADDR1,
|
||||
UIP_ETHADDR2,
|
||||
UIP_ETHADDR3,
|
||||
UIP_ETHADDR4,
|
||||
UIP_ETHADDR5}};
|
||||
UIP_ETHADDR1,
|
||||
UIP_ETHADDR2,
|
||||
UIP_ETHADDR3,
|
||||
UIP_ETHADDR4,
|
||||
UIP_ETHADDR5}};
|
||||
#else
|
||||
struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
|
||||
#endif
|
||||
|
||||
#ifndef UIP_CONF_EXTERNAL_BUFFER
|
||||
u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
|
||||
incoming packets. */
|
||||
incoming packets. */
|
||||
#endif /* UIP_CONF_EXTERNAL_BUFFER */
|
||||
|
||||
void *uip_appdata; /* The uip_appdata pointer points to
|
||||
application data. */
|
||||
application data. */
|
||||
void *uip_sappdata; /* The uip_appdata pointer points to
|
||||
the application data which is to
|
||||
be sent. */
|
||||
the application data which is to
|
||||
be sent. */
|
||||
#if UIP_URGDATA > 0
|
||||
void *uip_urgdata; /* The uip_urgdata pointer points to
|
||||
urgent data (out-of-band data), if
|
||||
present. */
|
||||
urgent data (out-of-band data), if
|
||||
present. */
|
||||
u16_t uip_urglen, uip_surglen;
|
||||
#endif /* UIP_URGDATA > 0 */
|
||||
|
||||
u16_t uip_len, uip_slen;
|
||||
/* The uip_len is either 8 or 16 bits,
|
||||
depending on the maximum packet
|
||||
size. */
|
||||
u16_t uip_len, uip_slen; /* The uip_len is either 8 or 16 bits,
|
||||
depending on the maximum packet
|
||||
size. */
|
||||
|
||||
u8_t uip_flags; /* The uip_flags variable is used for
|
||||
communication between the TCP/IP stack
|
||||
and the application program. */
|
||||
u8_t uip_flags; /* The uip_flags variable is used for
|
||||
communication between the TCP/IP stack
|
||||
and the application program. */
|
||||
|
||||
#if UIP_TCP
|
||||
struct uip_conn *uip_conn; /* uip_conn always points to the current
|
||||
connection. */
|
||||
connection. */
|
||||
|
||||
struct uip_conn uip_conns[UIP_CONNS];
|
||||
/* The uip_conns array holds all TCP
|
||||
connections. */
|
||||
connections. */
|
||||
u16_t uip_listenports[UIP_LISTENPORTS];
|
||||
/* The uip_listenports list all currently
|
||||
listning ports. */
|
||||
|
||||
listning ports. */
|
||||
|
||||
u8_t uip_forced_poll; // 1 if forcing the polling, 0 if the polling is not forced
|
||||
#endif /* UIP_TCP */
|
||||
|
||||
@ -184,19 +183,19 @@ struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
||||
#endif /* UIP_UDP */
|
||||
|
||||
static u16_t ipid; /* Ths ipid variable is an increasing
|
||||
number that is used for the IP ID
|
||||
field. */
|
||||
number that is used for the IP ID
|
||||
field. */
|
||||
|
||||
void uip_setipid(u16_t id) { ipid = id; }
|
||||
|
||||
#if UIP_TCP
|
||||
static u8_t iss[4]; /* The iss variable is used for the TCP
|
||||
initial sequence number. */
|
||||
initial sequence number. */
|
||||
#endif /* UIP_TCP */
|
||||
|
||||
#if UIP_ACTIVE_OPEN
|
||||
static u16_t lastport; /* Keeps track of the last port used for
|
||||
a new connection. */
|
||||
a new connection. */
|
||||
#endif /* UIP_ACTIVE_OPEN */
|
||||
|
||||
/* Temporary variables. */
|
||||
@ -290,7 +289,7 @@ uip_add32(u8_t *op32, u16_t op16)
|
||||
if(uip_acc32[2] == 0) {
|
||||
++uip_acc32[1];
|
||||
if(uip_acc32[1] == 0) {
|
||||
++uip_acc32[0];
|
||||
++uip_acc32[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,11 +309,11 @@ chksum(u16_t sum, const u8_t *data, u16_t len)
|
||||
dataptr = data;
|
||||
last_byte = data + len - 1;
|
||||
|
||||
while(dataptr < last_byte) { /* At least two more bytes */
|
||||
while(dataptr < last_byte) { /* At least two more bytes */
|
||||
t = (dataptr[0] << 8) + dataptr[1];
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
sum++; /* carry */
|
||||
}
|
||||
dataptr += 2;
|
||||
}
|
||||
@ -323,7 +322,7 @@ chksum(u16_t sum, const u8_t *data, u16_t len)
|
||||
t = (dataptr[0] << 8) + 0;
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
sum++; /* carry */
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,7 +370,7 @@ upper_layer_chksum(u8_t proto)
|
||||
|
||||
/* Sum TCP header and data. */
|
||||
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
|
||||
upper_layer_len);
|
||||
upper_layer_len);
|
||||
|
||||
return (sum == 0) ? 0xffff : htons(sum);
|
||||
}
|
||||
@ -496,8 +495,8 @@ uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
|
||||
}
|
||||
if(cconn->tcpstateflags == UIP_TIME_WAIT) {
|
||||
if(conn == 0 ||
|
||||
cconn->timer > conn->timer) {
|
||||
conn = cconn;
|
||||
cconn->timer > conn->timer) {
|
||||
conn = cconn;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -606,7 +605,7 @@ uip_listen(u16_t port)
|
||||
static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
|
||||
static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
|
||||
static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
|
||||
0x0f, 0x07, 0x03, 0x01};
|
||||
0x0f, 0x07, 0x03, 0x01};
|
||||
static u16_t uip_reasslen;
|
||||
static u8_t uip_reassflags;
|
||||
#define UIP_REASS_FLAG_LASTFRAG 0x01
|
||||
@ -655,28 +654,28 @@ uip_reass(void)
|
||||
/* Copy the fragment into the reassembly buffer, at the right
|
||||
offset. */
|
||||
memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
|
||||
(char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
|
||||
len);
|
||||
(char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
|
||||
len);
|
||||
|
||||
/* Update the bitmap. */
|
||||
if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
||||
/* If the two endpoints are in the same byte, we only update
|
||||
that byte. */
|
||||
|
||||
that byte. */
|
||||
|
||||
uip_reassbitmap[offset / (8 * 8)] |=
|
||||
bitmap_bits[(offset / 8 ) & 7] &
|
||||
~bitmap_bits[((offset + len) / 8 ) & 7];
|
||||
bitmap_bits[(offset / 8 ) & 7] &
|
||||
~bitmap_bits[((offset + len) / 8 ) & 7];
|
||||
} else {
|
||||
/* If the two endpoints are in different bytes, we update the
|
||||
bytes in the endpoints and fill the stuff inbetween with
|
||||
0xff. */
|
||||
bytes in the endpoints and fill the stuff inbetween with
|
||||
0xff. */
|
||||
uip_reassbitmap[offset / (8 * 8)] |=
|
||||
bitmap_bits[(offset / 8 ) & 7];
|
||||
bitmap_bits[(offset / 8 ) & 7];
|
||||
for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
|
||||
uip_reassbitmap[i] = 0xff;
|
||||
uip_reassbitmap[i] = 0xff;
|
||||
}
|
||||
uip_reassbitmap[(offset + len) / (8 * 8)] |=
|
||||
~bitmap_bits[((offset + len) / 8 ) & 7];
|
||||
~bitmap_bits[((offset + len) / 8 ) & 7];
|
||||
}
|
||||
|
||||
/* If this fragment has the More Fragments flag set to zero, we
|
||||
@ -695,27 +694,27 @@ uip_reass(void)
|
||||
in the bitmap are set. */
|
||||
if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
|
||||
/* Check all bytes up to and including all but the last byte in
|
||||
the bitmap. */
|
||||
the bitmap. */
|
||||
for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
|
||||
if(uip_reassbitmap[i] != 0xff) {
|
||||
goto nullreturn;
|
||||
}
|
||||
if(uip_reassbitmap[i] != 0xff) {
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
/* Check the last byte in the bitmap. It should contain just the
|
||||
right amount of bits. */
|
||||
right amount of bits. */
|
||||
if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
|
||||
(u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
|
||||
goto nullreturn;
|
||||
(u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
|
||||
goto nullreturn;
|
||||
}
|
||||
|
||||
/* If we have come this far, we have a full packet in the
|
||||
buffer, so we allocate a pbuf and copy the packet into it. We
|
||||
also reset the timer. */
|
||||
buffer, so we allocate a pbuf and copy the packet into it. We
|
||||
also reset the timer. */
|
||||
uip_reasstmr = 0;
|
||||
memcpy(BUF, FBUF, uip_reasslen);
|
||||
|
||||
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
|
||||
from now on. */
|
||||
from now on. */
|
||||
BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
|
||||
BUF->len[0] = uip_reasslen >> 8;
|
||||
BUF->len[1] = uip_reasslen & 0xff;
|
||||
@ -764,9 +763,10 @@ uip_process(u8_t flag)
|
||||
if(flag == UIP_POLL_REQUEST) {
|
||||
if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
|
||||
!uip_outstanding(uip_connr)) {
|
||||
uip_flags = UIP_POLL;
|
||||
UIP_APPCALL();
|
||||
goto appsend;
|
||||
uip_flags = UIP_POLL;
|
||||
uip_len = uip_slen = 0;
|
||||
UIP_APPCALL();
|
||||
goto appsend;
|
||||
}
|
||||
goto drop;
|
||||
|
||||
@ -780,9 +780,9 @@ uip_process(u8_t flag)
|
||||
/* Increase the initial sequence number. */
|
||||
if(++iss[3] == 0) {
|
||||
if(++iss[2] == 0) {
|
||||
if(++iss[1] == 0) {
|
||||
++iss[0];
|
||||
}
|
||||
if(++iss[1] == 0) {
|
||||
++iss[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -798,80 +798,80 @@ uip_process(u8_t flag)
|
||||
uip_connr->tcpstateflags == UIP_FIN_WAIT_2)) {
|
||||
++(uip_connr->timer);
|
||||
if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
}
|
||||
} else if(uip_connr->tcpstateflags != UIP_CLOSED && uip_connr->tcpstateflags != UIP_RESERVED) {
|
||||
/* If the connection has outstanding data, we increase the
|
||||
connection's timer and see if it has reached the RTO value
|
||||
in which case we retransmit. */
|
||||
connection's timer and see if it has reached the RTO value
|
||||
in which case we retransmit. */
|
||||
if(uip_outstanding(uip_connr) && !uip_forced_poll) {
|
||||
if(uip_connr->timer-- == 0) {
|
||||
if(uip_connr->nrtx == UIP_MAXRTX ||
|
||||
((uip_connr->tcpstateflags == UIP_SYN_SENT ||
|
||||
uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
|
||||
uip_connr->nrtx == UIP_MAXSYNRTX)) {
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
if(uip_connr->timer-- == 0) {
|
||||
if(uip_connr->nrtx == UIP_MAXRTX ||
|
||||
((uip_connr->tcpstateflags == UIP_SYN_SENT ||
|
||||
uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
|
||||
uip_connr->nrtx == UIP_MAXSYNRTX)) {
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
|
||||
/* We call UIP_APPCALL() with uip_flags set to
|
||||
UIP_TIMEDOUT to inform the application that the
|
||||
connection has timed out. */
|
||||
uip_flags = UIP_TIMEDOUT;
|
||||
UIP_APPCALL();
|
||||
/* We call UIP_APPCALL() with uip_flags set to
|
||||
UIP_TIMEDOUT to inform the application that the
|
||||
connection has timed out. */
|
||||
uip_flags = UIP_TIMEDOUT;
|
||||
UIP_APPCALL();
|
||||
|
||||
/* We also send a reset packet to the remote host. */
|
||||
BUF->flags = TCP_RST | TCP_ACK;
|
||||
goto tcp_send_nodata;
|
||||
}
|
||||
/* We also send a reset packet to the remote host. */
|
||||
BUF->flags = TCP_RST | TCP_ACK;
|
||||
goto tcp_send_nodata;
|
||||
}
|
||||
|
||||
/* Exponential backoff. */
|
||||
uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
|
||||
4:
|
||||
uip_connr->nrtx);
|
||||
++(uip_connr->nrtx);
|
||||
|
||||
/* Ok, so we need to retransmit. We do this differently
|
||||
depending on which state we are in. In ESTABLISHED, we
|
||||
call upon the application so that it may prepare the
|
||||
data for the retransmit. In SYN_RCVD, we resend the
|
||||
SYNACK that we sent earlier and in LAST_ACK we have to
|
||||
retransmit our FINACK. */
|
||||
UIP_STAT(++uip_stat.tcp.rexmit);
|
||||
switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
|
||||
case UIP_SYN_RCVD:
|
||||
/* In the SYN_RCVD state, we should retransmit our
|
||||
/* Exponential backoff. */
|
||||
uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
|
||||
4:
|
||||
uip_connr->nrtx);
|
||||
++(uip_connr->nrtx);
|
||||
|
||||
/* Ok, so we need to retransmit. We do this differently
|
||||
depending on which state we are in. In ESTABLISHED, we
|
||||
call upon the application so that it may prepare the
|
||||
data for the retransmit. In SYN_RCVD, we resend the
|
||||
SYNACK that we sent earlier and in LAST_ACK we have to
|
||||
retransmit our FINACK. */
|
||||
UIP_STAT(++uip_stat.tcp.rexmit);
|
||||
switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
|
||||
case UIP_SYN_RCVD:
|
||||
/* In the SYN_RCVD state, we should retransmit our
|
||||
SYNACK. */
|
||||
goto tcp_send_synack;
|
||||
|
||||
goto tcp_send_synack;
|
||||
|
||||
#if UIP_ACTIVE_OPEN
|
||||
case UIP_SYN_SENT:
|
||||
/* In the SYN_SENT state, we retransmit out SYN. */
|
||||
BUF->flags = 0;
|
||||
goto tcp_send_syn;
|
||||
case UIP_SYN_SENT:
|
||||
/* In the SYN_SENT state, we retransmit out SYN. */
|
||||
BUF->flags = 0;
|
||||
goto tcp_send_syn;
|
||||
#endif /* UIP_ACTIVE_OPEN */
|
||||
|
||||
case UIP_ESTABLISHED:
|
||||
/* In the ESTABLISHED state, we call upon the application
|
||||
|
||||
case UIP_ESTABLISHED:
|
||||
/* In the ESTABLISHED state, we call upon the application
|
||||
to do the actual retransmit after which we jump into
|
||||
the code for sending out the packet (the apprexmit
|
||||
label). */
|
||||
uip_flags = UIP_REXMIT;
|
||||
UIP_APPCALL();
|
||||
goto apprexmit;
|
||||
|
||||
case UIP_FIN_WAIT_1:
|
||||
case UIP_CLOSING:
|
||||
case UIP_LAST_ACK:
|
||||
/* In all these states we should retransmit a FINACK. */
|
||||
goto tcp_send_finack;
|
||||
|
||||
}
|
||||
}
|
||||
uip_flags = UIP_REXMIT;
|
||||
UIP_APPCALL();
|
||||
goto apprexmit;
|
||||
|
||||
case UIP_FIN_WAIT_1:
|
||||
case UIP_CLOSING:
|
||||
case UIP_LAST_ACK:
|
||||
/* In all these states we should retransmit a FINACK. */
|
||||
goto tcp_send_finack;
|
||||
|
||||
}
|
||||
}
|
||||
} else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
|
||||
/* If there was no need for a retransmission, we poll the
|
||||
/* If there was no need for a retransmission, we poll the
|
||||
application for new data. */
|
||||
uip_flags = UIP_POLL;
|
||||
UIP_APPCALL();
|
||||
goto appsend;
|
||||
uip_flags = UIP_POLL;
|
||||
UIP_APPCALL();
|
||||
goto appsend;
|
||||
}
|
||||
}
|
||||
goto drop;
|
||||
@ -928,14 +928,14 @@ uip_process(u8_t flag)
|
||||
uip_len = (BUF->len[0] << 8) + BUF->len[1];
|
||||
#if UIP_CONF_IPV6
|
||||
uip_len += 40; /* The length reported in the IPv6 header is the
|
||||
length of the payload that follows the
|
||||
header. However, uIP uses the uip_len variable
|
||||
for holding the size of the entire packet,
|
||||
including the IP header. For IPv4 this is not a
|
||||
problem as the length field in the IPv4 header
|
||||
contains the length of the entire packet. But
|
||||
for IPv6 we need to add the size of the IPv6
|
||||
header (40 bytes). */
|
||||
length of the payload that follows the
|
||||
header. However, uIP uses the uip_len variable
|
||||
for holding the size of the entire packet,
|
||||
including the IP header. For IPv4 this is not a
|
||||
problem as the length field in the IPv4 header
|
||||
contains the length of the entire packet. But
|
||||
for IPv6 we need to add the size of the IPv6
|
||||
header (40 bytes). */
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
} else {
|
||||
UIP_LOG("ip: packet shorter than reported in IP header.");
|
||||
@ -982,7 +982,7 @@ uip_process(u8_t flag)
|
||||
if(BUF->proto == UIP_PROTO_UDP &&
|
||||
uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
|
||||
/*&&
|
||||
uip_ipchksum() == 0xffff*/) {
|
||||
uip_ipchksum() == 0xffff*/) {
|
||||
goto udp_input;
|
||||
}
|
||||
#endif /* UIP_BROADCAST */
|
||||
@ -1009,7 +1009,7 @@ uip_process(u8_t flag)
|
||||
|
||||
#if !UIP_CONF_IPV6
|
||||
if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
|
||||
checksum. */
|
||||
checksum. */
|
||||
UIP_STAT(++uip_stat.ip.drop);
|
||||
UIP_STAT(++uip_stat.ip.chkerr);
|
||||
UIP_LOG("ip: bad checksum.");
|
||||
@ -1019,8 +1019,8 @@ uip_process(u8_t flag)
|
||||
|
||||
#if UIP_TCP
|
||||
if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
|
||||
proceed with TCP input
|
||||
processing. */
|
||||
proceed with TCP input
|
||||
processing. */
|
||||
goto tcp_input;
|
||||
}
|
||||
#endif /* UIP_TCP */
|
||||
@ -1034,7 +1034,7 @@ uip_process(u8_t flag)
|
||||
#if !UIP_CONF_IPV6
|
||||
/* ICMPv4 processing code follows. */
|
||||
if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
|
||||
here. */
|
||||
here. */
|
||||
UIP_STAT(++uip_stat.ip.drop);
|
||||
UIP_STAT(++uip_stat.ip.protoerr);
|
||||
UIP_LOG("ip: neither tcp nor icmp.");
|
||||
@ -1088,7 +1088,7 @@ uip_process(u8_t flag)
|
||||
DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
|
||||
|
||||
if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from
|
||||
here. */
|
||||
here. */
|
||||
UIP_STAT(++uip_stat.ip.drop);
|
||||
UIP_STAT(++uip_stat.ip.protoerr);
|
||||
UIP_LOG("ip: neither tcp nor icmp6.");
|
||||
@ -1103,12 +1103,12 @@ uip_process(u8_t flag)
|
||||
if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
|
||||
|
||||
if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
|
||||
/* Save the sender's address in our neighbor list. */
|
||||
uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
|
||||
/* Save the sender's address in our neighbor list. */
|
||||
uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
|
||||
}
|
||||
|
||||
/* We should now send a neighbor advertisement back to where the
|
||||
neighbor solicication came from. */
|
||||
neighbor solicication came from. */
|
||||
ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
|
||||
ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
|
||||
|
||||
@ -1188,8 +1188,8 @@ uip_process(u8_t flag)
|
||||
UDPBUF->srcport == uip_udp_conn->rport ||
|
||||
uip_udp_conn->rport == HTONS(69)) &&
|
||||
(uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
|
||||
uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
|
||||
uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
|
||||
uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
|
||||
uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
|
||||
goto udp_found;
|
||||
}
|
||||
}
|
||||
@ -1197,6 +1197,7 @@ uip_process(u8_t flag)
|
||||
goto drop;
|
||||
|
||||
udp_found:
|
||||
UIP_STAT(++uip_stat.udp.recv);
|
||||
#if UIP_TCP
|
||||
uip_conn = NULL;
|
||||
#endif /* UIP_TCP */
|
||||
@ -1232,7 +1233,7 @@ uip_process(u8_t flag)
|
||||
uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
|
||||
uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
|
||||
|
||||
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
|
||||
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
|
||||
|
||||
#if UIP_UDP_CHECKSUMS
|
||||
/* Calculate UDP checksum. */
|
||||
@ -1242,6 +1243,7 @@ uip_process(u8_t flag)
|
||||
}
|
||||
#endif /* UIP_UDP_CHECKSUMS */
|
||||
|
||||
UIP_STAT(++uip_stat.udp.sent);
|
||||
goto ip_send_nolen;
|
||||
#endif /* UIP_UDP */
|
||||
|
||||
@ -1253,7 +1255,7 @@ uip_process(u8_t flag)
|
||||
/* Start of TCP input header processing code. */
|
||||
|
||||
if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
|
||||
checksum. */
|
||||
checksum. */
|
||||
UIP_STAT(++uip_stat.tcp.drop);
|
||||
UIP_STAT(++uip_stat.tcp.chkerr);
|
||||
UIP_LOG("tcp: bad checksum.");
|
||||
@ -1269,6 +1271,10 @@ uip_process(u8_t flag)
|
||||
BUF->destport == uip_connr->lport &&
|
||||
BUF->srcport == uip_connr->rport &&
|
||||
uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
|
||||
if ((uip_connr->tcpstateflags != UIP_SYN_RCVD) &&
|
||||
(BUF->flags & TCP_CTL) == TCP_SYN) {
|
||||
goto reset;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
@ -1326,7 +1332,7 @@ uip_process(u8_t flag)
|
||||
if(++BUF->ackno[3] == 0) {
|
||||
if(++BUF->ackno[2] == 0) {
|
||||
if(++BUF->ackno[1] == 0) {
|
||||
++BUF->ackno[0];
|
||||
++BUF->ackno[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1361,8 +1367,8 @@ uip_process(u8_t flag)
|
||||
}
|
||||
if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
|
||||
if(uip_connr == 0 ||
|
||||
uip_conns[c].timer > uip_connr->timer) {
|
||||
uip_connr = &uip_conns[c];
|
||||
uip_conns[c].timer > uip_connr->timer) {
|
||||
uip_connr = &uip_conns[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1405,30 +1411,30 @@ uip_process(u8_t flag)
|
||||
for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
|
||||
opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
|
||||
if(opt == TCP_OPT_END) {
|
||||
/* End of options. */
|
||||
break;
|
||||
/* End of options. */
|
||||
break;
|
||||
} else if(opt == TCP_OPT_NOOP) {
|
||||
++c;
|
||||
/* NOP option. */
|
||||
++c;
|
||||
/* NOP option. */
|
||||
} else if(opt == TCP_OPT_MSS &&
|
||||
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
|
||||
/* An MSS option with the right option length. */
|
||||
tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
|
||||
(u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
|
||||
uip_connr->initialmss = uip_connr->mss =
|
||||
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
|
||||
/* And we are done processing options. */
|
||||
break;
|
||||
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
|
||||
/* An MSS option with the right option length. */
|
||||
tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
|
||||
(u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
|
||||
uip_connr->initialmss = uip_connr->mss =
|
||||
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
|
||||
/* And we are done processing options. */
|
||||
break;
|
||||
} else {
|
||||
/* All other options have a length field, so that we easily
|
||||
can skip past them. */
|
||||
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
|
||||
/* If the length field is zero, the options are malformed
|
||||
and we don't process them further. */
|
||||
break;
|
||||
}
|
||||
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
|
||||
/* All other options have a length field, so that we easily
|
||||
can skip past them. */
|
||||
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
|
||||
/* If the length field is zero, the options are malformed
|
||||
and we don't process them further. */
|
||||
break;
|
||||
}
|
||||
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1480,14 +1486,18 @@ uip_process(u8_t flag)
|
||||
|
||||
/* First, check if the sequence number of the incoming packet is
|
||||
what we're expecting next. If not, we send out an ACK with the
|
||||
correct numbers in. */
|
||||
if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
|
||||
((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
|
||||
correct numbers in, unless we are in the SYN_RCVD state and
|
||||
receive a SYN, in which case we should retransmit our SYNACK
|
||||
(which is done futher down). */
|
||||
if(!((((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
|
||||
((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) ||
|
||||
(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_RCVD) &&
|
||||
((BUF->flags & TCP_CTL) == TCP_SYN)))) {
|
||||
if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
|
||||
(BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
|
||||
BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
|
||||
BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
|
||||
BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
|
||||
BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
|
||||
BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
|
||||
BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
|
||||
goto tcp_send_ack;
|
||||
}
|
||||
}
|
||||
@ -1508,21 +1518,21 @@ uip_process(u8_t flag)
|
||||
uip_connr->snd_nxt[1] = uip_acc32[1];
|
||||
uip_connr->snd_nxt[2] = uip_acc32[2];
|
||||
uip_connr->snd_nxt[3] = uip_acc32[3];
|
||||
|
||||
|
||||
|
||||
/* Do RTT estimation, unless we have done retransmissions. */
|
||||
if(uip_connr->nrtx == 0) {
|
||||
signed char m;
|
||||
m = uip_connr->rto - uip_connr->timer;
|
||||
/* This is taken directly from VJs original code in his paper */
|
||||
m = m - (uip_connr->sa >> 3);
|
||||
uip_connr->sa += m;
|
||||
if(m < 0) {
|
||||
m = -m;
|
||||
}
|
||||
m = m - (uip_connr->sv >> 2);
|
||||
uip_connr->sv += m;
|
||||
uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
|
||||
signed char m;
|
||||
m = uip_connr->rto - uip_connr->timer;
|
||||
/* This is taken directly from VJs original code in his paper */
|
||||
m = m - (uip_connr->sa >> 3);
|
||||
uip_connr->sa += m;
|
||||
if(m < 0) {
|
||||
m = -m;
|
||||
}
|
||||
m = m - (uip_connr->sv >> 2);
|
||||
uip_connr->sv += m;
|
||||
uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
|
||||
|
||||
}
|
||||
/* Set the acknowledged flag. */
|
||||
@ -1539,9 +1549,9 @@ uip_process(u8_t flag)
|
||||
/* Do different things depending on in what state the connection is. */
|
||||
switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
|
||||
/* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
|
||||
implemented, since we force the application to close when the
|
||||
peer sends a FIN (hence the application goes directly from
|
||||
ESTABLISHED to LAST_ACK). */
|
||||
implemented, since we force the application to close when the
|
||||
peer sends a FIN (hence the application goes directly from
|
||||
ESTABLISHED to LAST_ACK). */
|
||||
case UIP_SYN_RCVD:
|
||||
/* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
|
||||
we are waiting for an ACK that acknowledges the data we sent
|
||||
@ -1559,6 +1569,10 @@ uip_process(u8_t flag)
|
||||
UIP_APPCALL();
|
||||
goto appsend;
|
||||
}
|
||||
/* We need to retransmit the SYNACK */
|
||||
if((BUF->flags & TCP_CTL) == TCP_SYN) {
|
||||
goto tcp_send_synack;
|
||||
}
|
||||
goto drop;
|
||||
#if UIP_ACTIVE_OPEN
|
||||
case UIP_SYN_SENT:
|
||||
@ -1571,35 +1585,35 @@ uip_process(u8_t flag)
|
||||
|
||||
/* Parse the TCP MSS option, if present. */
|
||||
if((BUF->tcpoffset & 0xf0) > 0x50) {
|
||||
for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
|
||||
opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
|
||||
if(opt == TCP_OPT_END) {
|
||||
/* End of options. */
|
||||
break;
|
||||
} else if(opt == TCP_OPT_NOOP) {
|
||||
++c;
|
||||
/* NOP option. */
|
||||
} else if(opt == TCP_OPT_MSS &&
|
||||
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
|
||||
/* An MSS option with the right option length. */
|
||||
tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
|
||||
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
|
||||
uip_connr->initialmss =
|
||||
uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
|
||||
opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
|
||||
if(opt == TCP_OPT_END) {
|
||||
/* End of options. */
|
||||
break;
|
||||
} else if(opt == TCP_OPT_NOOP) {
|
||||
++c;
|
||||
/* NOP option. */
|
||||
} else if(opt == TCP_OPT_MSS &&
|
||||
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
|
||||
/* An MSS option with the right option length. */
|
||||
tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
|
||||
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
|
||||
uip_connr->initialmss =
|
||||
uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
|
||||
/* And we are done processing options. */
|
||||
break;
|
||||
} else {
|
||||
/* All other options have a length field, so that we easily
|
||||
can skip past them. */
|
||||
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
|
||||
/* If the length field is zero, the options are malformed
|
||||
and we don't process them further. */
|
||||
break;
|
||||
}
|
||||
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
|
||||
}
|
||||
}
|
||||
/* And we are done processing options. */
|
||||
break;
|
||||
} else {
|
||||
/* All other options have a length field, so that we easily
|
||||
can skip past them. */
|
||||
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
|
||||
/* If the length field is zero, the options are malformed
|
||||
and we don't process them further. */
|
||||
break;
|
||||
}
|
||||
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
uip_connr->tcpstateflags = UIP_ESTABLISHED;
|
||||
uip_connr->rcv_nxt[0] = BUF->seqno[0];
|
||||
@ -1636,12 +1650,12 @@ uip_process(u8_t flag)
|
||||
|
||||
if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
|
||||
if(uip_outstanding(uip_connr)) {
|
||||
goto drop;
|
||||
goto drop;
|
||||
}
|
||||
uip_add_rcv_nxt(1 + uip_len);
|
||||
uip_flags |= UIP_CLOSE;
|
||||
if(uip_len > 0) {
|
||||
uip_flags |= UIP_NEWDATA;
|
||||
uip_flags |= UIP_NEWDATA;
|
||||
}
|
||||
UIP_APPCALL();
|
||||
uip_connr->len = 1;
|
||||
@ -1658,8 +1672,8 @@ uip_process(u8_t flag)
|
||||
#if UIP_URGDATA > 0
|
||||
uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
|
||||
if(uip_urglen > uip_len) {
|
||||
/* There is more urgent data in the next segment to come. */
|
||||
uip_urglen = uip_len;
|
||||
/* There is more urgent data in the next segment to come. */
|
||||
uip_urglen = uip_len;
|
||||
}
|
||||
uip_add_rcv_nxt(uip_urglen);
|
||||
uip_len -= uip_urglen;
|
||||
@ -1725,52 +1739,52 @@ uip_process(u8_t flag)
|
||||
appsend:
|
||||
|
||||
if(uip_flags & UIP_ABORT) {
|
||||
uip_slen = 0;
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
BUF->flags = TCP_RST | TCP_ACK;
|
||||
goto tcp_send_nodata;
|
||||
uip_slen = 0;
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
BUF->flags = TCP_RST | TCP_ACK;
|
||||
goto tcp_send_nodata;
|
||||
}
|
||||
|
||||
if(uip_flags & UIP_CLOSE) {
|
||||
uip_slen = 0;
|
||||
uip_connr->len = 1;
|
||||
uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
|
||||
uip_connr->nrtx = 0;
|
||||
BUF->flags = TCP_FIN | TCP_ACK;
|
||||
goto tcp_send_nodata;
|
||||
uip_slen = 0;
|
||||
uip_connr->len = 1;
|
||||
uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
|
||||
uip_connr->nrtx = 0;
|
||||
BUF->flags = TCP_FIN | TCP_ACK;
|
||||
goto tcp_send_nodata;
|
||||
}
|
||||
|
||||
/* If uip_slen > 0, the application has data to be sent. */
|
||||
if(uip_slen > 0) {
|
||||
|
||||
/* If the connection has acknowledged data, the contents of
|
||||
the ->len variable should be discarded. */
|
||||
if((uip_flags & UIP_ACKDATA) != 0) {
|
||||
uip_connr->len = 0;
|
||||
}
|
||||
/* If the connection has acknowledged data, the contents of
|
||||
the ->len variable should be discarded. */
|
||||
if((uip_flags & UIP_ACKDATA) != 0) {
|
||||
uip_connr->len = 0;
|
||||
}
|
||||
|
||||
/* If the ->len variable is non-zero the connection has
|
||||
already data in transit and cannot send anymore right
|
||||
now. */
|
||||
if(uip_connr->len == 0) {
|
||||
/* If the ->len variable is non-zero the connection has
|
||||
already data in transit and cannot send anymore right
|
||||
now. */
|
||||
if(uip_connr->len == 0) {
|
||||
|
||||
/* The application cannot send more than what is allowed by
|
||||
the mss (the minumum of the MSS and the available
|
||||
window). */
|
||||
if(uip_slen > uip_connr->mss) {
|
||||
uip_slen = uip_connr->mss;
|
||||
}
|
||||
/* The application cannot send more than what is allowed by
|
||||
the mss (the minumum of the MSS and the available
|
||||
window). */
|
||||
if(uip_slen > uip_connr->mss) {
|
||||
uip_slen = uip_connr->mss;
|
||||
}
|
||||
|
||||
/* Remember how much data we send out now so that we know
|
||||
when everything has been acknowledged. */
|
||||
uip_connr->len = uip_slen;
|
||||
} else {
|
||||
/* Remember how much data we send out now so that we know
|
||||
when everything has been acknowledged. */
|
||||
uip_connr->len = uip_slen;
|
||||
} else {
|
||||
|
||||
/* If the application already had unacknowledged data, we
|
||||
make sure that the application does not send (i.e.,
|
||||
retransmit) out more than it previously sent out. */
|
||||
uip_slen = uip_connr->len;
|
||||
}
|
||||
/* If the application already had unacknowledged data, we
|
||||
make sure that the application does not send (i.e.,
|
||||
retransmit) out more than it previously sent out. */
|
||||
uip_slen = uip_connr->len;
|
||||
}
|
||||
}
|
||||
uip_connr->nrtx = 0;
|
||||
apprexmit:
|
||||
@ -1779,19 +1793,19 @@ uip_process(u8_t flag)
|
||||
/* If the application has data to be sent, or if the incoming
|
||||
packet had new data in it, we must send out a packet. */
|
||||
if(uip_slen > 0 && uip_connr->len > 0) {
|
||||
/* Add the length of the IP and TCP headers. */
|
||||
uip_len = uip_connr->len + UIP_TCPIP_HLEN;
|
||||
/* We always set the ACK flag in response packets. */
|
||||
BUF->flags = TCP_ACK | TCP_PSH;
|
||||
/* Send the packet. */
|
||||
goto tcp_send_noopts;
|
||||
/* Add the length of the IP and TCP headers. */
|
||||
uip_len = uip_connr->len + UIP_TCPIP_HLEN;
|
||||
/* We always set the ACK flag in response packets. */
|
||||
BUF->flags = TCP_ACK | TCP_PSH;
|
||||
/* Send the packet. */
|
||||
goto tcp_send_noopts;
|
||||
}
|
||||
/* If there is no data to send, just send out a pure ACK if
|
||||
there is newdata. */
|
||||
there is newdata. */
|
||||
if(uip_flags & UIP_NEWDATA) {
|
||||
uip_len = UIP_TCPIP_HLEN;
|
||||
BUF->flags = TCP_ACK;
|
||||
goto tcp_send_noopts;
|
||||
uip_len = UIP_TCPIP_HLEN;
|
||||
BUF->flags = TCP_ACK;
|
||||
goto tcp_send_noopts;
|
||||
}
|
||||
}
|
||||
goto drop;
|
||||
@ -1814,11 +1828,11 @@ uip_process(u8_t flag)
|
||||
}
|
||||
if(BUF->flags & TCP_FIN) {
|
||||
if(uip_flags & UIP_ACKDATA) {
|
||||
uip_connr->tcpstateflags = UIP_TIME_WAIT;
|
||||
uip_connr->timer = 0;
|
||||
uip_connr->len = 0;
|
||||
uip_connr->tcpstateflags = UIP_TIME_WAIT;
|
||||
uip_connr->timer = 0;
|
||||
uip_connr->len = 0;
|
||||
} else {
|
||||
uip_connr->tcpstateflags = UIP_CLOSING;
|
||||
uip_connr->tcpstateflags = UIP_CLOSING;
|
||||
}
|
||||
uip_add_rcv_nxt(1);
|
||||
uip_flags = UIP_CLOSE;
|
||||
@ -1944,7 +1958,7 @@ uip_process(u8_t flag)
|
||||
UIP_STAT(++uip_stat.tcp.sent);
|
||||
send:
|
||||
DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
|
||||
(BUF->len[0] << 8) | BUF->len[1]);
|
||||
(BUF->len[0] << 8) | BUF->len[1]);
|
||||
|
||||
UIP_STAT(++uip_stat.ip.sent);
|
||||
/* Return and let the caller do the actual transmission. */
|
||||
|
104
src/uip/uip.h
104
src/uip/uip.h
@ -242,12 +242,12 @@ void uip_setipid(u16_t id);
|
||||
uip_input();
|
||||
if(uip_len > 0) {
|
||||
uip_arp_out();
|
||||
ethernet_devicedriver_send();
|
||||
ethernet_devicedriver_send();
|
||||
}
|
||||
} else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
|
||||
uip_arp_arpin();
|
||||
if(uip_len > 0) {
|
||||
ethernet_devicedriver_send();
|
||||
ethernet_devicedriver_send();
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
@ -926,7 +926,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
|
||||
*/
|
||||
#if !UIP_CONF_IPV6
|
||||
#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \
|
||||
((u16_t *)addr1)[1] == ((u16_t *)addr2)[1])
|
||||
((u16_t *)addr1)[1] == ((u16_t *)addr2)[1])
|
||||
#else /* !UIP_CONF_IPV6 */
|
||||
#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
|
||||
#endif /* !UIP_CONF_IPV6 */
|
||||
@ -1173,26 +1173,26 @@ struct uip_conn {
|
||||
|
||||
u16_t lport; /**< The local TCP port, in network byte order. */
|
||||
u16_t rport; /**< The local remote TCP port, in network byte
|
||||
order. */
|
||||
order. */
|
||||
|
||||
u8_t rcv_nxt[4]; /**< The sequence number that we expect to
|
||||
receive next. */
|
||||
receive next. */
|
||||
u8_t snd_nxt[4]; /**< The sequence number that was last sent by
|
||||
us. */
|
||||
u16_t len; /**< Length of the data that was previously sent. */
|
||||
u16_t mss; /**< Current maximum segment size for the
|
||||
connection. */
|
||||
connection. */
|
||||
u16_t initialmss; /**< Initial maximum segment size for the
|
||||
connection. */
|
||||
connection. */
|
||||
u8_t sa; /**< Retransmission time-out calculation state
|
||||
variable. */
|
||||
variable. */
|
||||
u8_t sv; /**< Retransmission time-out calculation state
|
||||
variable. */
|
||||
variable. */
|
||||
u8_t rto; /**< Retransmission time-out. */
|
||||
u8_t tcpstateflags; /**< TCP state and flags. */
|
||||
u8_t timer; /**< The retransmission timer. */
|
||||
u8_t nrtx; /**< The number of retransmissions for the last
|
||||
segment sent. */
|
||||
segment sent. */
|
||||
|
||||
/** The application state. */
|
||||
uip_tcp_appstate_t appstate;
|
||||
@ -1253,30 +1253,30 @@ extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
||||
struct uip_stats {
|
||||
struct {
|
||||
uip_stats_t drop; /**< Number of dropped packets at the IP
|
||||
layer. */
|
||||
layer. */
|
||||
uip_stats_t recv; /**< Number of received packets at the IP
|
||||
layer. */
|
||||
layer. */
|
||||
uip_stats_t sent; /**< Number of sent packets at the IP
|
||||
layer. */
|
||||
layer. */
|
||||
uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
|
||||
IP version or header length. */
|
||||
IP version or header length. */
|
||||
uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
|
||||
IP length, high byte. */
|
||||
IP length, high byte. */
|
||||
uip_stats_t lblenerr; /**< Number of packets dropped due to wrong
|
||||
IP length, low byte. */
|
||||
IP length, low byte. */
|
||||
uip_stats_t fragerr; /**< Number of packets dropped since they
|
||||
were IP fragments. */
|
||||
were IP fragments. */
|
||||
uip_stats_t chkerr; /**< Number of packets dropped due to IP
|
||||
checksum errors. */
|
||||
checksum errors. */
|
||||
uip_stats_t protoerr; /**< Number of packets dropped since they
|
||||
were neither ICMP, UDP nor TCP. */
|
||||
were neither ICMP, UDP nor TCP. */
|
||||
} ip; /**< IP statistics. */
|
||||
struct {
|
||||
uip_stats_t drop; /**< Number of dropped ICMP packets. */
|
||||
uip_stats_t recv; /**< Number of received ICMP packets. */
|
||||
uip_stats_t sent; /**< Number of sent ICMP packets. */
|
||||
uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
|
||||
type. */
|
||||
type. */
|
||||
} icmp; /**< ICMP statistics. */
|
||||
#if UIP_TCP
|
||||
struct {
|
||||
@ -1284,15 +1284,15 @@ struct uip_stats {
|
||||
uip_stats_t recv; /**< Number of recived TCP segments. */
|
||||
uip_stats_t sent; /**< Number of sent TCP segments. */
|
||||
uip_stats_t chkerr; /**< Number of TCP segments with a bad
|
||||
checksum. */
|
||||
checksum. */
|
||||
uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
|
||||
number. */
|
||||
number. */
|
||||
uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */
|
||||
uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
|
||||
uip_stats_t syndrop; /**< Number of dropped SYNs due to too few
|
||||
connections was avaliable. */
|
||||
connections was avaliable. */
|
||||
uip_stats_t synrst; /**< Number of SYNs for closed ports,
|
||||
triggering a RST. */
|
||||
triggering a RST. */
|
||||
} tcp; /**< TCP statistics. */
|
||||
#endif /* UIP_TCP */
|
||||
#if UIP_UDP
|
||||
@ -1301,7 +1301,7 @@ struct uip_stats {
|
||||
uip_stats_t recv; /**< Number of recived UDP segments. */
|
||||
uip_stats_t sent; /**< Number of sent UDP segments. */
|
||||
uip_stats_t chkerr; /**< Number of UDP segments with a bad
|
||||
checksum. */
|
||||
checksum. */
|
||||
} udp; /**< UDP statistics. */
|
||||
#endif /* UIP_UDP */
|
||||
};
|
||||
@ -1335,33 +1335,33 @@ extern u8_t uip_flags;
|
||||
functions/macros. */
|
||||
|
||||
#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
|
||||
acked and the application should send
|
||||
out new data instead of retransmitting
|
||||
the last data. */
|
||||
acked and the application should send
|
||||
out new data instead of retransmitting
|
||||
the last data. */
|
||||
#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
|
||||
us new data. */
|
||||
us new data. */
|
||||
#define UIP_REXMIT 4 /* Tells the application to retransmit the
|
||||
data that was last sent. */
|
||||
data that was last sent. */
|
||||
#define UIP_POLL 8 /* Used for polling the application, to
|
||||
check if the application has data that
|
||||
it wants to send. */
|
||||
check if the application has data that
|
||||
it wants to send. */
|
||||
#define UIP_CLOSE 16 /* The remote host has closed the
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to close the
|
||||
connection. */
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to close the
|
||||
connection. */
|
||||
#define UIP_ABORT 32 /* The remote host has aborted the
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to abort the
|
||||
connection. */
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to abort the
|
||||
connection. */
|
||||
#define UIP_CONNECTED 64 /* We have got a connection from a remote
|
||||
host and have set up a new connection
|
||||
for it, or an active connection has
|
||||
been successfully established. */
|
||||
|
||||
#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
|
||||
too many retransmissions. */
|
||||
too many retransmissions. */
|
||||
|
||||
/* uip_process(flag):
|
||||
*
|
||||
@ -1377,16 +1377,16 @@ void uip_process(u8_t flag);
|
||||
the macrose defined in this file. */
|
||||
|
||||
#define UIP_DATA 1 /* Tells uIP that there is incoming
|
||||
data in the uip_buf buffer. The
|
||||
length of the data is stored in the
|
||||
global variable uip_len. */
|
||||
data in the uip_buf buffer. The
|
||||
length of the data is stored in the
|
||||
global variable uip_len. */
|
||||
#define UIP_TIMER 2 /* Tells uIP that the periodic timer
|
||||
has fired. */
|
||||
has fired. */
|
||||
#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should
|
||||
be polled. */
|
||||
be polled. */
|
||||
#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram
|
||||
should be constructed in the
|
||||
uip_buf buffer. */
|
||||
should be constructed in the
|
||||
uip_buf buffer. */
|
||||
#if UIP_UDP
|
||||
#define UIP_UDP_TIMER 5
|
||||
#endif /* UIP_UDP */
|
||||
@ -1544,11 +1544,11 @@ struct uip_udpip_hdr {
|
||||
#define UIP_UDPH_LEN 8 /* Size of UDP header */
|
||||
#define UIP_TCPH_LEN 20 /* Size of TCP header */
|
||||
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP +
|
||||
UDP
|
||||
header */
|
||||
UDP
|
||||
header */
|
||||
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP +
|
||||
TCP
|
||||
header */
|
||||
TCP
|
||||
header */
|
||||
#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
|
||||
|
||||
|
||||
|
@ -174,13 +174,13 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
|
||||
/* Check if the source IP address of the incoming packet matches
|
||||
the IP address in this ARP table entry. */
|
||||
if(ipaddr[0] == tabptr->ipaddr[0] &&
|
||||
ipaddr[1] == tabptr->ipaddr[1]) {
|
||||
|
||||
/* An old entry found, update this and return. */
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
ipaddr[1] == tabptr->ipaddr[1]) {
|
||||
|
||||
/* An old entry found, update this and return. */
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,8 +205,8 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(arptime - tabptr->time > tmpage) {
|
||||
tmpage = arptime - tabptr->time;
|
||||
c = i;
|
||||
tmpage = arptime - tabptr->time;
|
||||
c = i;
|
||||
}
|
||||
}
|
||||
i = c;
|
||||
@ -238,7 +238,7 @@ void
|
||||
uip_arp_ipin(void)
|
||||
{
|
||||
uip_len -= sizeof(struct uip_eth_hdr);
|
||||
|
||||
|
||||
/* Only insert/update an entry if the source IP address of the
|
||||
incoming IP packet comes from a host on the local network. */
|
||||
if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
|
||||
@ -293,8 +293,8 @@ uip_arp_arpin(void)
|
||||
reply. */
|
||||
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
|
||||
/* First, we register the one who made the request in our ARP
|
||||
table, since it is likely that we will do more communication
|
||||
with this host in the future. */
|
||||
table, since it is likely that we will do more communication
|
||||
with this host in the future. */
|
||||
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
|
||||
|
||||
/* The reply opcode is 2. */
|
||||
@ -372,8 +372,8 @@ uip_arp_out(void)
|
||||
/* Check if the destination address is on the local network. */
|
||||
if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
|
||||
/* Destination address was not on the local network, so we need to
|
||||
use the default router's IP address instead of the destination
|
||||
address when determining the MAC address. */
|
||||
use the default router's IP address instead of the destination
|
||||
address when determining the MAC address. */
|
||||
uip_ipaddr_copy(ipaddr, uip_draddr);
|
||||
} else {
|
||||
/* Else, we use the destination IP address. */
|
||||
@ -383,13 +383,13 @@ uip_arp_out(void)
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == UIP_ARPTAB_SIZE) {
|
||||
/* The destination address was not in our ARP table, so we
|
||||
overwrite the IP packet with an ARP request. */
|
||||
overwrite the IP packet with an ARP request. */
|
||||
|
||||
memset(BUF->ethhdr.dest.addr, 0xff, 6);
|
||||
memset(BUF->dhwaddr.addr, 0x00, 6);
|
||||
|
@ -57,16 +57,16 @@ uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr)
|
||||
c = *addrstr;
|
||||
++j;
|
||||
if(j > 4) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if(c == '.' || c == 0) {
|
||||
*ipaddr = tmp;
|
||||
++ipaddr;
|
||||
tmp = 0;
|
||||
*ipaddr = tmp;
|
||||
++ipaddr;
|
||||
tmp = 0;
|
||||
} else if(c >= '0' && c <= '9') {
|
||||
tmp = (tmp * 10) + (c - '0');
|
||||
tmp = (tmp * 10) + (c - '0');
|
||||
} else {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
++addrstr;
|
||||
} while(c != '.' && c != 0);
|
||||
|
@ -660,62 +660,35 @@ builder.read_depends = function( self, ftable )
|
||||
return dtable
|
||||
end
|
||||
|
||||
-- Build and interpret dependencies for the given source files
|
||||
-- "flable" is either a space-separated string with all the source files or an array
|
||||
builder.make_depends = function( self, ftable )
|
||||
if type( ftable ) == 'string' then ftable = utils.string_to_table( ftable ) end
|
||||
|
||||
-- Start with initial dependency data (this might be nil when generated initially)
|
||||
local initdep = self:read_depends( ftable )
|
||||
|
||||
-- Build dependencies for all targets
|
||||
self.dtable = {}
|
||||
for i = 1, #ftable do
|
||||
local isasm = ftable[ i ]:find( "%.c$" ) == nil
|
||||
-- Skip assembler targets if 'asm_dep_cmd' is set to 'false'
|
||||
-- Skip C targets if 'c_dep_cmd' is set to 'false'
|
||||
local skip = isasm and self.asm_dep_cmd == false
|
||||
skip = skip or ( not isasm and self.c_dep_cmd == false )
|
||||
if not skip then
|
||||
local cmd = isasm and self._asm_cmd or self.comp_cmd
|
||||
local depcmd = cmd:gsub( "-c ", "-E -MM " )
|
||||
if isasm and self.asm_dep_cmd then depcmd = self.asm_dep_cmd end
|
||||
if not isasm and self.c_dep_cmd then depcmd = self.c_dep_cmd end
|
||||
local target = self:dep_target( ftable[ i ], initdep[ ftable[ i ] ], depcmd )
|
||||
-- The post build function will read the generated dependencies and save
|
||||
-- them into an instance-related field (dtable)
|
||||
target:set_post_build_function( function( t, _ )
|
||||
if not self.clean_mode then
|
||||
local tname = t.dep[ 1 ]:target_name()
|
||||
if tname then
|
||||
local fres = self:read_depends( tname )
|
||||
self.dtable[ tname ] = fres[ tname ]
|
||||
end
|
||||
end
|
||||
end )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Create and return compile targets for the given sources
|
||||
builder.create_compile_targets = function( self, ftable, res )
|
||||
if type( ftable ) == 'string' then ftable = utils.string_to_table( ftable ) end
|
||||
res = res or {}
|
||||
-- Build dependencies for all targets
|
||||
for i = 1, #ftable do
|
||||
local target
|
||||
local isasm = ftable[ i ]:find( "%.c$" ) == nil
|
||||
-- Skip assembler targets if 'asm_dep_cmd' is set to 'false'
|
||||
-- Skip C targets if 'c_dep_cmd' is set to 'false'
|
||||
local skip = isasm and self.asm_dep_cmd == false
|
||||
skip = skip or ( not isasm and self.c_dep_cmd == false )
|
||||
local deps = self:get_dep_filename( ftable[ i ] )
|
||||
if ftable[ i ]:find( "%.c$" ) then
|
||||
target = self:c_target( self:obj_name( ftable[ i ] ), { self:get_registered_target( deps ) or ftable[ i ] } )
|
||||
local target
|
||||
if not isasm then
|
||||
local depcmd = skip and self.comp_cmd or ( self.c_dep_cmd or self.comp_cmd:gsub( "-c ", sf( "-c -MD -MF %s ", deps ) ) )
|
||||
target = self:c_target( self:obj_name( ftable[ i ] ), { self:get_registered_target( deps ) or ftable[ i ] }, depcmd )
|
||||
else
|
||||
target = self:asm_target( self:obj_name( ftable[ i ] ), { self:get_registered_target( deps ) or ftable[ i ] } )
|
||||
local depcmd = skip and self._asm_cmd or ( self.asm_dep_cmd or self._asm_cmd:gsub( "-c ", sf( "-c -MD -MF %s ", deps ) ) )
|
||||
target = self:asm_target( self:obj_name( ftable[ i ] ), { self:get_registered_target( deps ) or ftable[ i ] }, depcmd )
|
||||
end
|
||||
-- Pre build step: replace dependencies with the ones from the compiler generated dependency file
|
||||
if not skip then
|
||||
target:set_pre_build_function( function( t, _ )
|
||||
if not self.clean_mode then
|
||||
local fres = self:read_depends( ftable[ i ] )
|
||||
t:set_dependencies( fres[ ftable[ i ] ] or ftable[ i ] )
|
||||
end
|
||||
end )
|
||||
end
|
||||
-- Post build step: replace dependencies with the ones generated by 'make_depends'
|
||||
target:set_pre_build_function( function( t, _ )
|
||||
if not self.clean_mode then
|
||||
t:set_dependencies( self.dtable[ ftable[ i ] ] or ftable[ i ] )
|
||||
end
|
||||
end )
|
||||
table.insert( res, target )
|
||||
end
|
||||
return res
|
||||
@ -778,7 +751,6 @@ end
|
||||
|
||||
-- Create dependencies, create object files, link final object
|
||||
builder.make_exe_target = function( self, target, file_list )
|
||||
self:make_depends( file_list )
|
||||
local odeps = self:create_compile_targets( file_list )
|
||||
local exetarget = self:link_target( target, odeps )
|
||||
self:default( self:add_target( exetarget ) )
|
||||
|
Loading…
x
Reference in New Issue
Block a user