1
0
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:
James Snyder 2011-10-04 21:24:00 -05:00
commit f9eec264db
61 changed files with 1614 additions and 1263 deletions

2
.gitignore vendored
View File

@ -17,4 +17,4 @@ doc/dist
doc/cache doc/cache
*~ *~
*.*~ *.*~
luac.cross*

View File

@ -457,7 +457,6 @@ builder:set_exe_extension( ".elf" )
-- Create the ROM file system -- Create the ROM file system
make_romfs() make_romfs()
-- Creaate executable targets -- Creaate executable targets
builder:make_depends( source_files )
odeps = builder:create_compile_targets( source_files ) odeps = builder:create_compile_targets( source_files )
exetarget = builder:link_target( output, odeps ) exetarget = builder:link_target( output, odeps )
-- This is also the default target -- This is also the default target

View File

@ -17,9 +17,9 @@ local components =
arch_platform = { "ll", "pio", "spi", "uart", "timers", "pwm", "cpu", "eth", "adc", "i2c", "can" }, 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_gen = { "bit", "pd", "cpu", "pack", "adc", "term", "pio", "uart", "spi", "tmr", "pwm", "net", "can", "rpc", "elua", "i2c" },
refman_ps_lm3s = { "disp" }, refman_ps_lm3s = { "disp" },
refman_ps_str9 = { "pio", "rtc" }, refman_ps_str9 = { "pio" },
refman_ps_mbed = { "pio" }, refman_ps_mbed = { "pio" },
refman_ps_mizar32 = { "disp" }, refman_ps_mizar32 = { "lcd" },
} }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------

View File

@ -23,34 +23,56 @@ data_en =
ret = "1 if the ADC interface exists, 0 otherwise" ret = "1 if the ADC interface exists, 0 otherwise"
}, },
{ sig = "u32 #platform_adc_op#( unsigned id, int op, u32 data );", { sig = "u32 #platform_adc_get_maxval#( unsigned id );",
desc = "Executes an operation on an ADC channel", desc = "Gets the maximum conversion value the channel may supply (based on channel resolution)",
args = 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", "$id$ - ADC channel ID",
[[$op$ - the operation that must be executed. It can take any value from @#adc_operations@this enum@, as follows: "$length$ - the length of the moving average filter (must be a power of 2). If it is 1, the filter is disabled.",
<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."
}, },
ret = ret = "$PLATFORM_OK$ if the operation succeeded, $PLATFORM_ERR$ otherwise."
{
"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"
}
}, },
{ 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 );", { 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", desc = "Checks whether a timer may be used with a particular ADC channel",
args = args =
@ -63,64 +85,4 @@ data_en =
} }
} }
data_pt = data_pt = data_en
{
-- 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",
}
}
}

View File

@ -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", 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 );", { sig = "u32 #platform_pwm_start#( unsigned id );",
desc = "Executes an operation on a PWM channel", desc = "Starts PWM generation on the specified channel",
args = args =
{ {
"$id$ - PWM channel ID", "$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> { sig = "u32 #platform_pwm_stop#( unsigned id );",
<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 desc = "Stops PWM generation on the specified channel",
@#platform_pwm_setup@platform_pwm_setup@) to $data$ hertz.</li> args =
<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 =
{ {
"the actual value of the base clock when $op$ == $PLATFORM_PWM_OP_SET_CLOCK$, which might be different than $data$ depending on the hardware", "$id$ - PWM channel ID",
"the value of the base clock when $op$ == $PLATFORM_PWM_OP_GET_CLOCK$", }
"irrelevant for other operations" },
}
} { 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"
},
} }
} }

View File

@ -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.", "$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." "$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 )", { sig = "status = #adc.isdone#( id )",
desc = "Check whether samples are still being acquired on a channel.", desc = "Check whether samples are still being acquired on a channel.",

View File

@ -31,7 +31,7 @@ $_C$. For example, to get the constants listed above declare your $PLATFORM_CPU_
_C( INT_GPIOB ),\ _C( INT_GPIOB ),\
................. .................
_C( INT_UDMA )~ _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.]] This mechanism is also used to expose interrupt IDs to the CPU module, check @inthandlers.html@here@ for an overview of eLua interrupt support.]]
}, },
}, },

View File

@ -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.", 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 = args =
{ {
"$id$ - the ID of the SPI interface.", "$id$ - the ID of the I2C interface.",
"$numbytes$ - the number of bytes to read." "$numbytes$ - the number of bytes to read."
}, },
ret = "a string with all the data read from the I2C interface." ret = "a string with all the data read from the I2C interface."

View File

@ -111,8 +111,7 @@ argument. The IP is given as a string.]],
"$port$ - the port to wait for connections from the remote system.", "$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 [[$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.]], 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 [[$timeout (optional)$ - the timeout, in microseconds, after which the accept function returns if no connection was requested.]]
be specified.]]
}, },
ret = ret =
{ {
@ -148,8 +147,7 @@ be specified.]]
</ul>]], </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 [[$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.]], 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 [[$timeout (optional)$ - the timeout, in microseconds, after which the recv function returns if no connection was requested.]]
be specified.]]
}, },
ret = ret =
{ {

View File

@ -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

View 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

View File

@ -10,7 +10,7 @@ data_en =
menu_name = "pio", menu_name = "pio",
-- Overview -- 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 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 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.]], @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.]],

View File

@ -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

View File

@ -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 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 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 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 <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 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> complete description of these modules.</p>

View File

@ -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 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 <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> 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> 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> </ul>
$$FOOTER$$ $$FOOTER$$

View File

@ -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 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 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 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 <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 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> complete description of these modules.</p>

View File

@ -9,6 +9,9 @@
#define BUILD_RPC #define BUILD_RPC
#define LUARPC_ENABLE_SERIAL #define LUARPC_ENABLE_SERIAL
#define LUA_PLATFORM_LIBS_REG \
{LUA_OSLIBNAME, luaopen_os}
#define LUA_PLATFORM_LIBS_ROM \ #define LUA_PLATFORM_LIBS_ROM \
_ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )\ _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )\
_ROM( AUXLIB_BITARRAY, luaopen_bitarray, bitarray_map )\ _ROM( AUXLIB_BITARRAY, luaopen_bitarray, bitarray_map )\

View File

@ -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) // There are 16 "virtual" PWM channels (PWM0...PWM15)
#define PLATFORM_PWM_TOTAL 16 #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 // The platform PWM functions
int platform_pwm_exists( unsigned id ); int platform_pwm_exists( unsigned id );
u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty ); 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 // CPU specific functions
@ -235,27 +229,22 @@ u32 platform_cpu_get_frequency();
// ***************************************************************************** // *****************************************************************************
// The platform ADC functions // 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 // Functions requiring platform-specific implementation
int platform_adc_update_sequence(); int platform_adc_update_sequence();
int platform_adc_start_sequence(); int platform_adc_start_sequence();
void platform_adc_stop( unsigned id ); 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 // ADC Common Functions
int platform_adc_exists( unsigned id ); int platform_adc_exists( unsigned id );
int platform_adc_check_timer_id( unsigned id, unsigned timer_id ); int platform_adc_check_timer_id( unsigned id, unsigned timer_id );
u32 platform_adc_op( unsigned id, int op, u32 data ); 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 // I2C platform interface

View File

@ -294,47 +294,41 @@ int platform_adc_exists( unsigned id )
#ifdef BUILD_ADC #ifdef BUILD_ADC
u32 platform_adc_op( unsigned id, int op, u32 data ) u32 platform_adc_get_maxval( unsigned id )
{ {
elua_adc_ch_state *s = adc_get_ch_state( id ); return pow( 2, ADC_BIT_RESOLUTION ) - 1;
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_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 #endif // #ifdef BUILD_ADC
// **************************************************************************** // ****************************************************************************

View File

@ -126,7 +126,7 @@ void adc_init_ch_state( unsigned id )
#endif #endif
// Set to run as fast as possible // 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 ) void adc_init_dev_state( unsigned dev_id )

View File

@ -34,6 +34,8 @@ static int math_abs (lua_State *L) {
return 1; return 1;
} }
#ifndef LUA_NUMBER_INTEGRAL
static int math_sin (lua_State *L) { static int math_sin (lua_State *L) {
lua_pushnumber(L, sin(luaL_checknumber(L, 1))); lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
return 1; return 1;
@ -107,6 +109,20 @@ static int math_modf (lua_State *L) {
return 2; 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 #ifdef LUA_NUMBER_INTEGRAL
// Integer square root for integer version // Integer square root for integer version
static lua_Number isqrt(lua_Number x) static lua_Number isqrt(lua_Number x)
@ -142,6 +158,8 @@ static int math_sqrt (lua_State *L) {
return 1; return 1;
} }
#ifndef LUA_NUMBER_INTEGRAL
static int math_pow (lua_State *L) { static int math_pow (lua_State *L) {
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1; return 1;
@ -184,7 +202,7 @@ static int math_ldexp (lua_State *L) {
return 1; return 1;
} }
#endif // #ifdef LUA_NUMBER_INTEGRAL
static int math_min (lua_State *L) { static int math_min (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */ 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[] = { const LUA_REG_TYPE math_map[] = {
#ifdef LUA_NUMBER_INTEGRAL #ifdef LUA_NUMBER_INTEGRAL
{LSTRKEY("abs"), LFUNCVAL(math_abs)}, {LSTRKEY("abs"), LFUNCVAL(math_abs)},
{LSTRKEY("ceil"), LFUNCVAL(math_identity)},
{LSTRKEY("floor"), LFUNCVAL(math_identity)},
{LSTRKEY("max"), LFUNCVAL(math_max)}, {LSTRKEY("max"), LFUNCVAL(math_max)},
{LSTRKEY("min"), LFUNCVAL(math_min)}, {LSTRKEY("min"), LFUNCVAL(math_min)},
{LSTRKEY("random"), LFUNCVAL(math_random)}, {LSTRKEY("random"), LFUNCVAL(math_random)},

View File

@ -20,30 +20,30 @@ static int adc_maxval( lua_State* L )
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( adc, id ); 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 ); lua_pushinteger( L, res );
return 1; return 1;
} }
// Lua: realclock = setclock( id, clock, [timer_id] ) // Lua: realclock = setclock( id, freq, [timer_id] )
static int adc_setclock( lua_State* L ) static int adc_setclock( lua_State* L )
{ {
u32 clock; u32 freq;
unsigned id, timer_id = 0; unsigned id, timer_id = 0;
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( adc, id ); MOD_CHECK_ID( adc, id );
clock = luaL_checkinteger( L, 2 ); freq = luaL_checkinteger( L, 2 );
if ( clock > 0 ) if ( freq > 0 )
{ {
timer_id = luaL_checkinteger( L, 3 ); timer_id = luaL_checkinteger( L, 3 );
MOD_CHECK_ID( timer, timer_id ); MOD_CHECK_ID( timer, timer_id );
MOD_CHECK_RES_ID( adc, id, timer, timer_id ); MOD_CHECK_RES_ID( adc, id, timer, timer_id );
} }
platform_adc_op( id, PLATFORM_ADC_OP_SET_TIMER, timer_id ); platform_adc_set_timer( id, timer_id );
clock = platform_adc_op( id, PLATFORM_ADC_OP_SET_CLOCK, clock ); freq = platform_adc_set_clock( id, freq );
lua_pushinteger( L, clock ); lua_pushinteger( L, freq );
return 1; return 1;
} }
@ -54,7 +54,7 @@ static int adc_isdone( lua_State* L )
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( adc, id ); 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; return 1;
} }
@ -66,7 +66,7 @@ static int adc_setblocking( lua_State* L )
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( adc, id ); MOD_CHECK_ID( adc, id );
mode = luaL_checkinteger( L, 2 ); mode = luaL_checkinteger( L, 2 );
platform_adc_op( id, PLATFORM_ADC_SET_BLOCKING, mode ); platform_adc_set_blocking( id, mode );
return 0; return 0;
} }
@ -81,7 +81,7 @@ static int adc_setsmoothing( lua_State* L )
length = luaL_checkinteger( L, 2 ); length = luaL_checkinteger( L, 2 );
if ( !( length & ( length - 1 ) ) ) 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 ) if ( res == PLATFORM_ERR )
return luaL_error( L, "Buffer allocation failed." ); return luaL_error( L, "Buffer allocation failed." );
else else

View File

@ -68,7 +68,9 @@ static int i2c_write( lua_State *L )
return luaL_error( L, "invalid number of arguments" ); return luaL_error( L, "invalid number of arguments" );
for( argn = 2; argn <= lua_gettop( L ); argn ++ ) 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 ); numdata = ( int )luaL_checkinteger( L, argn );
if( numdata < 0 || numdata > 255 ) if( numdata < 0 || numdata > 255 )

View File

@ -31,7 +31,7 @@ static int pwm_start( lua_State* L )
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( pwm, id ); MOD_CHECK_ID( pwm, id );
platform_pwm_op( id, PLATFORM_PWM_OP_START, 0 ); platform_pwm_start( id );
return 0; return 0;
} }
@ -42,7 +42,7 @@ static int pwm_stop( lua_State* L )
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( pwm, id ); MOD_CHECK_ID( pwm, id );
platform_pwm_op( id, PLATFORM_PWM_OP_STOP, 0 ); platform_pwm_stop( id );
return 0; return 0;
} }
@ -55,7 +55,7 @@ static int pwm_setclock( lua_State* L )
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( pwm, id ); MOD_CHECK_ID( pwm, id );
clk = luaL_checkinteger( L, 2 ); 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 ); lua_pushinteger( L, clk );
return 1; return 1;
} }
@ -68,7 +68,7 @@ static int pwm_getclock( lua_State* L )
id = luaL_checkinteger( L, 1 ); id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( pwm, id ); 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 ); lua_pushinteger( L, clk );
return 1; return 1;
} }

View File

@ -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 ) ); res = platform_timer_set_match_int( id, ( u32 )luaL_checknumber( L, 2 ), ( int )luaL_checkinteger( L, 3 ) );
if( res == PLATFORM_TIMER_INT_TOO_SHORT ) if( res == PLATFORM_TIMER_INT_TOO_SHORT )
return luaL_error( L, "timer interval too small" ); 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 ) 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; return 0;
} }
#endif // #ifdef BUILD_LUA_INT_HANDLERS #endif // #ifdef BUILD_LUA_INT_HANDLERS

View File

@ -338,8 +338,8 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
// PWM pins // PWM pins
static const Pin pwm_pins[] = { PIN_PWMC_PWM0, PIN_PWMC_PWM1, PIN_PWMC_PWM2, PIN_PWMC_PWM3 }; static const Pin pwm_pins[] = { PIN_PWMC_PWM0, PIN_PWMC_PWM1, PIN_PWMC_PWM2, PIN_PWMC_PWM3 };
// Helper function: return the PWM clock // Return the PWM clock
static u32 platform_pwm_get_clock( unsigned id ) u32 platform_pwm_get_clock( unsigned id )
{ {
u32 cfg = AT91C_BASE_PWMC->PWMC_CH[ id ].PWMC_CMR; u32 cfg = AT91C_BASE_PWMC->PWMC_CH[ id ].PWMC_CMR;
u16 clkdata; u16 clkdata;
@ -358,8 +358,8 @@ static u32 platform_pwm_get_clock( unsigned id )
} }
} }
// Helper function: set the PWM clock // Set the PWM clock
static u32 platform_pwm_set_clock( unsigned id, u32 clock ) u32 platform_pwm_set_clock( unsigned id, u32 clock )
{ {
if( id < 2 ) if( id < 2 )
PWMC_ConfigureClocks( clock, 0, BOARD_MCK ); PWMC_ConfigureClocks( clock, 0, BOARD_MCK );
@ -386,30 +386,14 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
return pwmclk / period; return pwmclk / period;
} }
u32 platform_pwm_op( unsigned id, int op, u32 data ) void platform_pwm_start( unsigned id )
{ {
u32 res = 0; volatile u32 dummy;
PIO_Configure( pwm_pins + id, 1 );
switch( op ) dummy = AT91C_BASE_PWMC->PWMC_ISR;
{
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;
} }
void platform_pwm_stop( unsigned id )
{
platform_pio_op( 1, 1 << ( 19 + id ), PLATFORM_IO_PIN_DIR_INPUT );
}

View File

@ -14,6 +14,7 @@
#define BUILD_CON_GENERIC #define BUILD_CON_GENERIC
//#define BUILD_RPC //#define BUILD_RPC
#define BUILD_C_INT_HANDLERS #define BUILD_C_INT_HANDLERS
#define BUILD_ADC
// ***************************************************************************** // *****************************************************************************
// UART/Timer IDs configuration data (used in main.c) // UART/Timer IDs configuration data (used in main.c)
@ -43,6 +44,12 @@
#define BUILD_RPC #define BUILD_RPC
#endif #endif
#ifdef BUILD_ADC
#define ADCLINE _ROM( AUXLIB_ADC, luaopen_adc, adc_map )
#else
#define ADCLINE
#endif
#if defined( BUILD_RPC ) #if defined( BUILD_RPC )
#define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map ) #define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )
#else #else
@ -57,6 +64,7 @@
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\ _ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
_ROM( AUXLIB_TERM, luaopen_term, term_map )\ _ROM( AUXLIB_TERM, luaopen_term, term_map )\
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\ _ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
ADCLINE\
RPCLINE\ RPCLINE\
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\ _ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\ _ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
@ -78,8 +86,8 @@
#else #else
#define NUM_TIMER 3 #define NUM_TIMER 3
#endif #endif
#define NUM_PWM 0 #define NUM_PWM 7
#define NUM_ADC 0 #define NUM_ADC 8
#define NUM_CAN 0 #define NUM_CAN 0
// RPC boot options // RPC boot options
@ -91,6 +99,11 @@
#define BUF_ENABLE_UART #define BUF_ENABLE_UART
#define CON_BUF_SIZE BUF_SIZE_128 #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 // SD/MMC Filesystem Setup
#define MMCFS_TICK_HZ 10 #define MMCFS_TICK_HZ 10
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ ) #define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )

View File

@ -22,6 +22,7 @@
//#define BUILD_RPC //#define BUILD_RPC
#define BUF_ENABLE_UART #define BUF_ENABLE_UART
#define BUILD_C_INT_HANDLERS #define BUILD_C_INT_HANDLERS
#define BUILD_LUA_INT_HANDLERS
//#define BUILD_RFS //#define BUILD_RFS
//#define BUILD_SERMUX //#define BUILD_SERMUX
@ -32,9 +33,9 @@
// Build options for 256KB and 512KB flash // Build options for 256KB and 512KB flash
# define RAM_SIZE 0x10000 # define RAM_SIZE 0x10000
# define BUILD_ADC # define BUILD_ADC
# define BUILD_LCD
# define BUILD_TERM # define BUILD_TERM
# define BUILD_UIP # define BUILD_UIP
# define ENABLE_DISP
#endif #endif
#ifdef BUILD_UIP #ifdef BUILD_UIP
@ -47,7 +48,7 @@
// Auxiliary libraries that will be compiled for this platform // Auxiliary libraries that will be compiled for this platform
// The name of the platform specific libs table // The name of the platform specific libs table
#ifdef ENABLE_DISP #ifdef BUILD_LCD
#define PS_LIB_TABLE_NAME "mizar32" #define PS_LIB_TABLE_NAME "mizar32"
#endif #endif
@ -109,7 +110,7 @@
#define RPCLINE #define RPCLINE
#endif #endif
#ifdef PS_LIB_TABLE_NAME #if defined( PS_LIB_TABLE_NAME )
#define PLATLINE _ROM( PS_LIB_TABLE_NAME, luaopen_platform, platform_map ) #define PLATLINE _ROM( PS_LIB_TABLE_NAME, luaopen_platform, platform_map )
#else #else
#define PLATLINE #define PLATLINE

View File

@ -1,6 +1,6 @@
-- Configuration file for the AVR32 microcontrollers -- 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" ) addm( "FORAVR32" )
-- See board.h for possible BOARD values. -- See board.h for possible BOARD values.

View File

@ -1,6 +1,6 @@
# Configuration file for the AVR32 microcontrollers # 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') comp.Append(CPPDEFINES = 'FORAVR32')
# See board.h for possible BOARD values. # See board.h for possible BOARD values.

View File

@ -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 );
}

View File

@ -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

View File

@ -196,6 +196,8 @@ void i2c_start_cond(void)
while (READSCL() == 0) while (READSCL() == 0)
; // You can add a timeout to this loop to ; // You can add a timeout to this loop to
// recover from SCL being stuck low. // recover from SCL being stuck low.
// Repeated start setup time, minimum 4.7us
I2CDELAY();
} }
if (READSDA() == 0) if (READSDA() == 0)
ARBITRATION_LOST(); ARBITRATION_LOST();
@ -214,7 +216,9 @@ void i2c_stop_cond(void)
/* Clock stretching */ /* Clock stretching */
while (READSCL() == 0) while (READSCL() == 0)
; /* You should add timeout to this loop */ ; /* 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) if (READSDA() == 0)
ARBITRATION_LOST(); ARBITRATION_LOST();
I2CDELAY(); I2CDELAY();

View File

@ -1,5 +1,7 @@
// Declarations for the low-level AVR32 I2C driver for eLua // Declarations for the low-level AVR32 I2C driver for eLua
#include "type.h" // for u32
u32 i2c_setup( u32 speed ); // speed is in Hz u32 i2c_setup( u32 speed ); // speed is in Hz
void i2c_start_cond( void ); void i2c_start_cond( void );
void i2c_stop_cond( void ); void i2c_stop_cond( void );

392
src/platform/avr32/lcd.c Normal file
View 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
View 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

View File

@ -41,15 +41,21 @@
#include "pwm.h" #include "pwm.h"
#include "i2c.h" #include "i2c.h"
#ifdef BUILD_UIP
// UIP sys tick data // UIP sys tick data
// NOTE: when using virtual timers, SYSTICKHZ and VTMR_FREQ_HZ should have the // 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) // 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) #define SYSTICKMS (1000 / SYSTICKHZ)
#ifdef BUILD_UIP
static int eth_timer_fired; static int eth_timer_fired;
#endif
#endif // BUILD_UIP
// **************************************************************************** // ****************************************************************************
// Platform initialization // 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; return 0;
} }
@ -821,15 +827,27 @@ int platform_adc_start_sequence( )
# error "NUM_PWM > AVR32_PWM_CHANNEL_LENGTH" # error "NUM_PWM > AVR32_PWM_CHANNEL_LENGTH"
#endif #endif
#if NUM_PWM > 0
static const gpio_map_t pwm_pins = static const gpio_map_t pwm_pins =
{ {
{ AVR32_PWM_0_PIN, AVR32_PWM_0_FUNCTION }, #if ( BOARD == ATEVK1100 ) || ( BOARD == MIZAR32 )
{ AVR32_PWM_1_PIN, AVR32_PWM_1_FUNCTION }, { AVR32_PWM_0_PIN, AVR32_PWM_0_FUNCTION }, // PB19 - LED4
{ AVR32_PWM_2_PIN, AVR32_PWM_2_FUNCTION }, { AVR32_PWM_1_PIN, AVR32_PWM_1_FUNCTION }, // PB20 - LED5
{ AVR32_PWM_3_PIN, AVR32_PWM_3_FUNCTION }, { AVR32_PWM_2_PIN, AVR32_PWM_2_FUNCTION }, // PB21 - LED6
{ AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PB27 { AVR32_PWM_3_PIN, AVR32_PWM_3_FUNCTION }, // PB22 - LED7
{ AVR32_PWM_5_1_PIN, AVR32_PWM_5_1_FUNCTION }, // PB28 { AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PB27 - LED0
{ AVR32_PWM_6_PIN, AVR32_PWM_6_FUNCTION }, { 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 #undef prescalers
static u32 pwm_set_clock_freq( u32 freq ) u32 platform_pwm_set_clock( unsigned id, u32 freq )
{ {
unsigned pre, div; unsigned pre, div;
@ -938,31 +956,23 @@ static u32 pwm_set_clock_freq( u32 freq )
return pwm_get_clock_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 return pwm_get_clock_freq();
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;
} }
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 // I2C support
@ -1102,12 +1112,12 @@ u32 platform_eth_get_elapsed_time()
#include "lrotable.h" #include "lrotable.h"
#include "lrodefs.h" #include "lrodefs.h"
extern const LUA_REG_TYPE disp_map[]; extern const LUA_REG_TYPE lcd_map[];
const LUA_REG_TYPE platform_map[] = const LUA_REG_TYPE platform_map[] =
{ {
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "disp" ), LROVAL( disp_map ) }, { LSTRKEY( "lcd" ), LROVAL( lcd_map ) },
#endif #endif
{ LNILKEY, LNILVAL } { LNILKEY, LNILVAL }
}; };
@ -1121,8 +1131,8 @@ LUALIB_API int luaopen_platform( lua_State *L )
// Setup the new tables inside platform table // Setup the new tables inside platform table
lua_newtable( L ); lua_newtable( L );
luaL_register( L, NULL, disp_map ); luaL_register( L, NULL, lcd_map );
lua_setfield( L, -2, "disp" ); lua_setfield( L, -2, "lcd" );
return 1; return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0 #endif // #if LUA_OPTIMIZE_MEMORY > 0

View File

@ -103,9 +103,3 @@ const LUA_REG_TYPE disp_map[] =
{ LSTRKEY( "draw" ), LFUNCVAL( disp_imageDraw ) }, { LSTRKEY( "draw" ), LFUNCVAL( disp_imageDraw ) },
{ LNILKEY, LNILVAL } { LNILKEY, LNILVAL }
}; };
LUALIB_API int luaopen_disp( lua_State *L )
{
LREGISTER( L, AUXLIB_DISP, disp_map );
}

View File

@ -624,8 +624,8 @@ static void pwms_init()
MAP_SysCtlPWMClockSet( SYSCTL_PWMDIV_1 ); MAP_SysCtlPWMClockSet( SYSCTL_PWMDIV_1 );
} }
// Helper function: return the PWM clock // Return the PWM clock
static u32 platform_pwm_get_clock() u32 platform_pwm_get_clock( unsigned id )
{ {
unsigned i; unsigned i;
u32 clk; u32 clk;
@ -637,8 +637,8 @@ static u32 platform_pwm_get_clock()
return MAP_SysCtlClockGet() / pwm_div_data[ i ]; return MAP_SysCtlClockGet() / pwm_div_data[ i ];
} }
// Helper function: set the PWM clock // Set the PWM clock
static u32 platform_pwm_set_clock( u32 clock ) u32 platform_pwm_set_clock( unsigned id, u32 clock )
{ {
unsigned i, min_i; unsigned i, min_i;
u32 sysclk; 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 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
{ {
u32 pwmclk = platform_pwm_get_clock(); u32 pwmclk = platform_pwm_get_clock( id );
u32 period; u32 period;
#if defined( FORLM3S9B92 ) || defined(FORLM3S9D92) #if defined( FORLM3S9B92 ) || defined(FORLM3S9D92)
@ -673,32 +673,16 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
return pwmclk / period; 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 ) void platform_pwm_stop( unsigned id )
{ {
case PLATFORM_PWM_OP_SET_CLOCK: MAP_PWMOutputState( PWM_BASE, 1 << id, false );
res = platform_pwm_set_clock( data ); MAP_PWMGenDisable( PWM_BASE, pwm_gens[ id >> 1 ] );
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;
} }
// ***************************************************************************** // *****************************************************************************
@ -818,12 +802,12 @@ static void adcs_init()
adc_init_ch_state( id ); adc_init_ch_state( id );
// Perform sequencer setup // Perform sequencer setup
platform_adc_setclock( 0, 0 ); platform_adc_set_clock( 0, 0 );
MAP_ADCIntEnable( ADC_BASE, d->seq_id ); MAP_ADCIntEnable( ADC_BASE, d->seq_id );
MAP_IntEnable( adc_ints[ 0 ] ); // Enable sequencer 0 int 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 ); elua_adc_dev_state *d = adc_get_dev_state( 0 );

View File

@ -427,12 +427,12 @@ static void platform_setup_adcs()
// Default enables ADC interrupt only on global, switch to per-channel // Default enables ADC interrupt only on global, switch to per-channel
ADC_IntConfig( LPC_ADC, ADC_ADGINTEN, DISABLE ); 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 // 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_TIMERCFG_Type TIM_ConfigStruct;
TIM_MATCHCFG_Type TIM_MatchConfigStruct ; TIM_MATCHCFG_Type TIM_MatchConfigStruct ;
@ -538,13 +538,13 @@ int platform_adc_start_sequence()
// Helper function: get timer clock // 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 ); return CLKPWR_GetPCLK( CLKPWR_PCLKSEL_PWM1 ) / ( LPC_PWM1->PR + 1 );
} }
// Helper function: set timer clock // 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; 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; 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 ) void platform_pwm_stop( unsigned id )
{ {
case PLATFORM_PWM_OP_START: PWM_Cmd(LPC_PWM1, DISABLE);
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;
} }
// **************************************************************************** // ****************************************************************************

View File

@ -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 // 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 ); elua_adc_dev_state *d = adc_get_dev_state( 0 );
@ -799,8 +799,8 @@ enum
PWM_ENABLE_6 = 1 << 14, PWM_ENABLE_6 = 1 << 14,
}; };
// Helper function: get timer clock // Get timer clock
static u32 platform_pwm_get_clock( unsigned id ) u32 platform_pwm_get_clock( unsigned id )
{ {
unsigned pwmid = id / 6; unsigned pwmid = id / 6;
PREG PWMxPR = ( PREG )pwm_pr[ pwmid ]; PREG PWMxPR = ( PREG )pwm_pr[ pwmid ];
@ -808,8 +808,8 @@ static u32 platform_pwm_get_clock( unsigned id )
return Fpclk / ( *PWMxPR + 1 ); return Fpclk / ( *PWMxPR + 1 );
} }
// Helper function: set timer clock // Set timer clock
static u32 platform_pwm_set_clock( unsigned id, u32 clock ) u32 platform_pwm_set_clock( unsigned id, u32 clock )
{ {
u32 div = Fpclk / clock, prevtc; u32 div = Fpclk / clock, prevtc;
unsigned pwmid = id / 6; 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; 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; unsigned pwmid = id / 6;
PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ]; PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ];
PREG PWMxPCR = ( PREG )pwm_pcr[ pwmid ]; PREG PWMxPCR = ( PREG )pwm_pcr[ pwmid ];
switch( op ) *PWMxPCR = PWM_ENABLE_1 | PWM_ENABLE_2 | PWM_ENABLE_3 | PWM_ENABLE_4 | PWM_ENABLE_5 | PWM_ENABLE_6;
{ *PWMxTCR = PWM_ENABLE | PWM_MODE;
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;
} }
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;
}

View File

@ -692,13 +692,15 @@ int platform_s_uart_set_flow_control( unsigned id, int type )
// **************************************************************************** // ****************************************************************************
// Timers // Timers
u8 stm32_timer_int_periodic_flag[ NUM_PHYS_TIMER ];
// We leave out TIM6/TIM for now, as they are dedicated // 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_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_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 #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 ) void SysTick_Handler( void )
{ {
@ -723,17 +725,17 @@ static void timers_init()
// Configure timers // Configure timers
for( i = 0; i < NUM_TIMER; i ++ ) 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 ]; TIM_TypeDef* ptimer = timer[ id ];
return TIM_GET_BASE_CLK( id ) / ( TIM_GetPrescaler( ptimer ) + 1 ); 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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TypeDef *ptimer = timer[ id ]; TIM_TypeDef *ptimer = timer[ id ];
@ -756,7 +758,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
volatile unsigned dummy; volatile unsigned dummy;
timer_data_type final; 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 ); TIM_SetCounter( ptimer, 0 );
for( dummy = 0; dummy < 200; dummy ++ ); for( dummy = 0; dummy < 200; dummy ++ );
while( TIM_GetCounter( ptimer ) < final ); while( TIM_GetCounter( ptimer ) < final );
@ -789,11 +791,11 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
break; break;
case PLATFORM_TIMER_OP_SET_CLOCK: case PLATFORM_TIMER_OP_SET_CLOCK:
res = timer_set_clock( id, data ); res = platform_timer_set_clock( id, data );
break; break;
case PLATFORM_TIMER_OP_GET_CLOCK: case PLATFORM_TIMER_OP_GET_CLOCK:
res = timer_get_clock( id ); res = platform_timer_get_clock( id );
break; 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 ) 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 // Return the PWM clock
// NOTE: Can't find a function to query for the period set for the timer, therefore using the struct. // NOTE: Can't find a function to query for the period set for the timer,
// This may require adjustment if driver libraries are updated. // therefore using the struct.
static u32 platform_pwm_get_clock() // 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 ) ); 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 // Set the PWM clock
static u32 platform_pwm_set_clock( u32 clock ) u32 platform_pwm_set_clock( unsigned id, u32 clock )
{ {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TypeDef* ptimer = PWM_TIMER_NAME; TIM_TypeDef* ptimer = PWM_TIMER_NAME;
@ -872,7 +922,7 @@ static u32 platform_pwm_set_clock( u32 clock )
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;
TIM_TimeBaseInit( ptimer, &TIM_TimeBaseStructure ); 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 ) 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_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure);
clock = platform_pwm_set_clock( frequency ); clock = platform_pwm_set_clock( id, frequency );
TIM_ARRPreloadConfig( ptimer, ENABLE ); TIM_ARRPreloadConfig( ptimer, ENABLE );
/* PWM Mode configuration */ /* PWM Mode configuration */
@ -931,30 +981,14 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
return clock; 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 ) void platform_pwm_stop( unsigned id )
{ {
case PLATFORM_PWM_OP_SET_CLOCK: PWM_TIMER_NAME->CCER &= ~( ( u16 )1 << 4 * id );
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;
} }
// ***************************************************************************** // *****************************************************************************
@ -1148,10 +1182,10 @@ static void adcs_init()
DMA_Cmd( DMA1_Channel1, ENABLE ); DMA_Cmd( DMA1_Channel1, ENABLE );
DMA_ITConfig( DMA1_Channel1, DMA1_IT_TC1 , 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; TIM_TimeBaseInitTypeDef timer_base_struct;
elua_adc_dev_state *d = adc_get_dev_state( 0 ); elua_adc_dev_state *d = adc_get_dev_state( 0 );

View File

@ -112,6 +112,7 @@
#define NUM_SPI 2 #define NUM_SPI 2
#define NUM_UART 5 #define NUM_UART 5
#define NUM_TIMER 5 #define NUM_TIMER 5
#define NUM_PHYS_TIMER 5
#define NUM_PWM 4 #define NUM_PWM 4
#define NUM_ADC 16 #define NUM_ADC 16
#define NUM_CAN 1 #define NUM_CAN 1

View File

@ -9,6 +9,10 @@
// Platform-specific headers // Platform-specific headers
#include "stm32f10x.h" #include "stm32f10x.h"
#ifndef VTMR_TIMER_ID
#define VTMR_TIMER_ID ( -1 )
#endif
// **************************************************************************** // ****************************************************************************
// Interrupt handlers // 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 // GPIO helper functions
@ -234,19 +293,30 @@ static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear )
// **************************************************************************** // ****************************************************************************
// Interrupt: INT_TMR_MATCH // 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 ) 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 ) 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 // 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 }; 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() void platform_int_init()
{ {
NVIC_InitTypeDef nvic_init_structure; NVIC_InitTypeDef nvic_init_structure;
@ -295,7 +374,8 @@ void platform_int_init()
// Enable all USART interrupts in the NVIC // Enable all USART interrupts in the NVIC
nvic_init_structure.NVIC_IRQChannelPreemptionPriority = 0; nvic_init_structure.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init_structure.NVIC_IRQChannelSubPriority = 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 ++ ) for( i = 0; i < sizeof( uart_irq_table ) / sizeof( u8 ); i ++ )
{ {
nvic_init_structure.NVIC_IRQChannel = uart_irq_table[ i ]; nvic_init_structure.NVIC_IRQChannel = uart_irq_table[ i ];
@ -309,6 +389,15 @@ void platform_int_init()
NVIC_Init( &nvic_init_structure ); 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
} }
// **************************************************************************** // ****************************************************************************

View File

@ -319,31 +319,26 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
return pwmclk / period; 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; return platform_timer_set_clock( id + 1, clock );
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;
} }
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 );
}

View File

@ -524,12 +524,12 @@ static void platform_setup_adcs()
ADC_ITConfig(ADC_IT_ECV, ENABLE); 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 // 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 ); 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; 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 ]; TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
u32 base = ( SCU_GetPCLKFreqValue() * 1000 ); u32 base = ( SCU_GetPCLKFreqValue() * 1000 );
@ -668,31 +668,25 @@ static u32 platform_pwm_set_clock( unsigned id, u32 clock )
return base / div; 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 ]; TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
switch( op ) return ( SCU_GetPCLKFreqValue() * 1000 ) / ( TIM_GetPrescalerValue( p_timer ) + 1 );
{ }
case PLATFORM_PWM_OP_START:
TIM_CounterCmd( p_timer, TIM_START );
break;
case PLATFORM_PWM_OP_STOP: void platform_pwm_start( unsigned id )
TIM_CounterCmd( p_timer, TIM_STOP ); {
break; TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
case PLATFORM_PWM_OP_SET_CLOCK: TIM_CounterCmd( p_timer, TIM_START );
res = platform_pwm_set_clock( id, data ); }
break;
case PLATFORM_PWM_OP_GET_CLOCK: void platform_pwm_stop( unsigned id )
res = ( SCU_GetPCLKFreqValue() * 1000 ) / ( TIM_GetPrescalerValue( p_timer ) + 1 ); {
break; TIM_TypeDef* p_timer = ( TIM_TypeDef* )str9_timer_data[ id ];
}
return res; TIM_CounterCmd( p_timer, TIM_STOP );
} }
// **************************************************************************** // ****************************************************************************

View File

@ -71,22 +71,3 @@ const LUA_REG_TYPE str9_pio_map[] =
{ LSTRKEY( "setpin" ), LFUNCVAL( setpin) }, { LSTRKEY( "setpin" ), LFUNCVAL( setpin) },
{ LNILKEY, LNILVAL } { 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
}

View File

@ -276,17 +276,17 @@ PT_THREAD(handle_dhcp(void))
s.timer_init = platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_START, 0 ); 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 ); 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) { if(uip_newdata() && parse_msg() == DHCPOFFER) {
uip_flags &= ~UIP_NEWDATA; uip_flags &= ~UIP_NEWDATA;
s.state = STATE_OFFER_RECEIVED; s.state = STATE_OFFER_RECEIVED;
break; break;
} }
uip_flags &= ~UIP_NEWDATA; uip_flags &= ~UIP_NEWDATA;
if(s.ticks < CLOCK_SECOND * 60) { if(s.ticks < CLOCK_SECOND * 60) {
s.ticks *= 2; s.ticks *= 2;
} else { } else {
s.ipaddr[0] = 0; s.ipaddr[0] = 0;
goto dhcp_failed; goto dhcp_failed;
} }
} while(s.state != STATE_OFFER_RECEIVED); } while(s.state != STATE_OFFER_RECEIVED);
s.ticks = CLOCK_SECOND; 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 ); 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) { if(uip_newdata() && parse_msg() == DHCPACK) {
uip_flags &= ~UIP_NEWDATA; uip_flags &= ~UIP_NEWDATA;
s.state = STATE_CONFIG_RECEIVED; s.state = STATE_CONFIG_RECEIVED;
break; break;
} }

View File

@ -55,7 +55,7 @@
*/ */
#ifndef __LC_SWITCH_H__ #ifndef __LC_SWITCH_H__
#define __LC_SWTICH_H__ #define __LC_SWITCH_H__
/* WARNING! lc implementation using switch() does not work if an /* WARNING! lc implementation using switch() does not work if an
LC_SET() is done within another switch() statement! */ LC_SET() is done within another switch() statement! */

View File

@ -76,7 +76,7 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
buf_setup(struct psock_buf *buf, buf_setup(struct psock_buf *buf,
u8_t *bufptr, u16_t bufsize) u8_t *bufptr, u16_t bufsize)
{ {
buf->ptr = bufptr; buf->ptr = bufptr;
buf->left = bufsize; buf->left = bufsize;
@ -84,7 +84,7 @@ buf_setup(struct psock_buf *buf,
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static u8_t static u8_t
buf_bufdata(struct psock_buf *buf, u16_t len, 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) { if(*datalen < buf->left) {
memcpy(buf->ptr, *dataptr, *datalen); memcpy(buf->ptr, *dataptr, *datalen);
@ -112,7 +112,7 @@ buf_bufdata(struct psock_buf *buf, u16_t len,
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static u8_t static u8_t
buf_bufto(register struct psock_buf *buf, u8_t endmarker, 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; u8_t c;
while(buf->left > 0 && *datalen > 0) { 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, PT_THREAD(psock_send(register struct psock *s, const char *buf,
unsigned int len)) unsigned int len))
{ {
PT_BEGIN(&s->psockpt); 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 /* Save the length of and a pointer to the data that is to be
sent. */ sent. */
s->sendptr = buf; s->sendptr = (u8_t *)buf;
s->sendlen = len; s->sendlen = len;
s->state = STATE_NONE; 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, 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); PT_BEGIN(&s->psockpt);
@ -276,7 +276,7 @@ PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
{ {
PT_BEGIN(&psock->psockpt); 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 /* XXX: Should add buf_checkmarker() before do{} loop, if
incoming data has been handled while waiting for a write. */ 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(); psock->readlen = uip_datalen();
} }
} while((buf_bufto(&psock->buf, c, } while((buf_bufto(&psock->buf, c,
&psock->readptr, &psock->readptr,
&psock->readlen) & BUF_FOUND) == 0); &psock->readlen) & BUF_FOUND) == 0);
if(psock_datalen(psock) == 0) { if(psock_datalen(psock) == 0) {
psock->state = STATE_NONE; psock->state = STATE_NONE;
@ -303,7 +303,7 @@ PT_THREAD(psock_readbuf(register struct psock *psock))
{ {
PT_BEGIN(&psock->psockpt); 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 /* XXX: Should add buf_checkmarker() before do{} loop, if
incoming data has been handled while waiting for a write. */ 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(); psock->readlen = uip_datalen();
} }
} while(buf_bufdata(&psock->buf, psock->bufsize, } while(buf_bufdata(&psock->buf, psock->bufsize,
&psock->readptr, &psock->readptr,
&psock->readlen) != BUF_FULL); &psock->readlen) != BUF_FULL);
if(psock_datalen(psock) == 0) { if(psock_datalen(psock) == 0) {
psock->state = STATE_NONE; psock->state = STATE_NONE;
@ -334,7 +334,7 @@ psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
psock->readlen = 0; psock->readlen = 0;
psock->bufptr = buffer; psock->bufptr = buffer;
psock->bufsize = buffersize; psock->bufsize = buffersize;
buf_setup(&psock->buf, buffer, buffersize); buf_setup(&psock->buf, (u8_t *)buffer, buffersize);
PT_INIT(&psock->pt); PT_INIT(&psock->pt);
PT_INIT(&psock->psockpt); PT_INIT(&psock->psockpt);
} }

View File

@ -105,19 +105,19 @@ struct psock_buf {
*/ */
struct psock { struct psock {
struct pt pt, psockpt; /* Protothreads - one that's using the psock struct pt pt, psockpt; /* Protothreads - one that's using the psock
functions, and one that runs inside the functions, and one that runs inside the
psock functions. */ psock functions. */
const u8_t *sendptr; /* Pointer to the next data to be sent. */ const u8_t *sendptr; /* Pointer to the next data to be sent. */
u8_t *readptr; /* Pointer to the next data to be read. */ u8_t *readptr; /* Pointer to the next data to be read. */
char *bufptr; /* Pointer to the buffer used for buffering 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 sendlen; /* The number of bytes left to be sent. */
u16_t readlen; /* The number of bytes left to be read. */ u16_t readlen; /* The number of bytes left to be read. */
struct psock_buf buf; /* The structure holding the state of the 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 int bufsize; /* The size of the input buffer. */
unsigned char state; /* The state of the protosocket. */ 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 * \hideinitializer
*/ */
#define PSOCK_SEND(psock, data, datalen) \ #define PSOCK_SEND(psock, data, datalen) \
PT_WAIT_THREAD(&((psock)->pt), 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 * \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_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str)))
PT_THREAD(psock_generator_send(struct psock *psock, 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 * \brief Generate data with a function and send it
@ -216,9 +216,9 @@ PT_THREAD(psock_generator_send(struct psock *psock,
* *
* \hideinitializer * \hideinitializer
*/ */
#define PSOCK_GENERATOR_SEND(psock, generator, arg) \ #define PSOCK_GENERATOR_SEND(psock, generator, arg) \
PT_WAIT_THREAD(&((psock)->pt), \ PT_WAIT_THREAD(&((psock)->pt), \
psock_generator_send(psock, generator, arg)) psock_generator_send(psock, generator, arg))
/** /**
@ -247,7 +247,7 @@ PT_THREAD(psock_readbuf(struct psock *psock));
* *
* \hideinitializer * \hideinitializer
*/ */
#define PSOCK_READBUF(psock) \ #define PSOCK_READBUF(psock) \
PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock)) PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock))
PT_THREAD(psock_readto(struct psock *psock, unsigned char c)); 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 * \hideinitializer
*/ */
#define PSOCK_READTO(psock, c) \ #define PSOCK_READTO(psock, c) \
PT_WAIT_THREAD(&((psock)->pt), 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 * \hideinitializer
*/ */
#define PSOCK_CLOSE_EXIT(psock) \ #define PSOCK_CLOSE_EXIT(psock) \
do { \ do { \
PSOCK_CLOSE(psock); \ PSOCK_CLOSE(psock); \
PSOCK_EXIT(psock); \ PSOCK_EXIT(psock); \
} while(0) } while(0)
/** /**

View File

@ -145,12 +145,12 @@ struct pt {
* *
* \hideinitializer * \hideinitializer
*/ */
#define PT_WAIT_UNTIL(pt, condition) \ #define PT_WAIT_UNTIL(pt, condition) \
do { \ do { \
LC_SET((pt)->lc); \ LC_SET((pt)->lc); \
if(!(condition)) { \ if(!(condition)) { \
return PT_WAITING; \ return PT_WAITING; \
} \ } \
} while(0) } while(0)
/** /**
@ -203,10 +203,10 @@ struct pt {
* *
* \hideinitializer * \hideinitializer
*/ */
#define PT_SPAWN(pt, child, thread) \ #define PT_SPAWN(pt, child, thread) \
do { \ do { \
PT_INIT((child)); \ PT_INIT((child)); \
PT_WAIT_THREAD((pt), (thread)); \ PT_WAIT_THREAD((pt), (thread)); \
} while(0) } while(0)
/** @} */ /** @} */
@ -226,10 +226,10 @@ struct pt {
* *
* \hideinitializer * \hideinitializer
*/ */
#define PT_RESTART(pt) \ #define PT_RESTART(pt) \
do { \ do { \
PT_INIT(pt); \ PT_INIT(pt); \
return PT_WAITING; \ return PT_WAITING; \
} while(0) } while(0)
/** /**
@ -243,10 +243,10 @@ struct pt {
* *
* \hideinitializer * \hideinitializer
*/ */
#define PT_EXIT(pt) \ #define PT_EXIT(pt) \
do { \ do { \
PT_INIT(pt); \ PT_INIT(pt); \
return PT_EXITED; \ return PT_EXITED; \
} while(0) } while(0)
/** @} */ /** @} */
@ -287,13 +287,13 @@ struct pt {
* *
* \hideinitializer * \hideinitializer
*/ */
#define PT_YIELD(pt) \ #define PT_YIELD(pt) \
do { \ do { \
PT_YIELD_FLAG = 0; \ PT_YIELD_FLAG = 0; \
LC_SET((pt)->lc); \ LC_SET((pt)->lc); \
if(PT_YIELD_FLAG == 0) { \ if(PT_YIELD_FLAG == 0) { \
return PT_YIELDED; \ return PT_YIELDED; \
} \ } \
} while(0) } while(0)
/** /**
@ -307,13 +307,13 @@ struct pt {
* *
* \hideinitializer * \hideinitializer
*/ */
#define PT_YIELD_UNTIL(pt, cond) \ #define PT_YIELD_UNTIL(pt, cond) \
do { \ do { \
PT_YIELD_FLAG = 0; \ PT_YIELD_FLAG = 0; \
LC_SET((pt)->lc); \ LC_SET((pt)->lc); \
if((PT_YIELD_FLAG == 0) || !(cond)) { \ if((PT_YIELD_FLAG == 0) || !(cond)) { \
return PT_YIELDED; \ return PT_YIELDED; \
} \ } \
} while(0) } while(0)
/** @} */ /** @} */

View File

@ -181,23 +181,23 @@ check_entries(void)
if(namemapptr->state == STATE_NEW || if(namemapptr->state == STATE_NEW ||
namemapptr->state == STATE_ASKING) { namemapptr->state == STATE_ASKING) {
if(namemapptr->state == STATE_ASKING) { if(namemapptr->state == STATE_ASKING) {
if(--namemapptr->tmr == 0) { if(--namemapptr->tmr == 0) {
if(++namemapptr->retries == MAX_RETRIES) { if(++namemapptr->retries == MAX_RETRIES) {
namemapptr->state = STATE_ERROR; namemapptr->state = STATE_ERROR;
resolv_found(namemapptr->name, NULL); resolv_found(namemapptr->name, NULL);
continue; continue;
} }
namemapptr->tmr = namemapptr->retries; namemapptr->tmr = namemapptr->retries;
} else { } else {
/* printf("Timer %d\n", namemapptr->tmr);*/ /* printf("Timer %d\n", namemapptr->tmr);*/
/* Its timer has not run out, so we move on to next /* Its timer has not run out, so we move on to next
entry. */ entry. */
continue; continue;
} }
} else { } else {
namemapptr->state = STATE_ASKING; namemapptr->state = STATE_ASKING;
namemapptr->tmr = 1; namemapptr->tmr = 1;
namemapptr->retries = 0; namemapptr->retries = 0;
} }
hdr = (struct dns_hdr *)uip_appdata; hdr = (struct dns_hdr *)uip_appdata;
memset(hdr, 0, sizeof(struct dns_hdr)); memset(hdr, 0, sizeof(struct dns_hdr));
@ -209,20 +209,20 @@ check_entries(void)
--nameptr; --nameptr;
/* Convert hostname into suitable query format. */ /* Convert hostname into suitable query format. */
do { do {
++nameptr; ++nameptr;
nptr = query; nptr = query;
++query; ++query;
for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) { for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) {
*query = *nameptr; *query = *nameptr;
++query; ++query;
++n; ++n;
} }
*nptr = n; *nptr = n;
} while(*nameptr != 0); } while(*nameptr != 0);
{ {
static unsigned char endquery[] = static unsigned char endquery[] =
{0,0,1,0,1}; {0,0,1,0,1};
memcpy(query, endquery, 5); memcpy(query, endquery, 5);
} }
uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata)); uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata));
break; break;
@ -237,7 +237,7 @@ check_entries(void)
static void static void
newdata(void) newdata(void)
{ {
char *nameptr; unsigned char *nameptr;
struct dns_answer *ans; struct dns_answer *ans;
struct dns_hdr *hdr; struct dns_hdr *hdr;
static u8_t nquestions, nanswers; static u8_t nquestions, nanswers;
@ -281,44 +281,44 @@ newdata(void)
/* Skip the name in the question. XXX: This should really be /* Skip the name in the question. XXX: This should really be
checked agains the name in the question, to be sure that they checked agains the name in the question, to be sure that they
match. */ match. */
nameptr = parse_name((char *)uip_appdata + 12) + 4; nameptr = parse_name((unsigned char *)uip_appdata + 12) + 4;
while(nanswers > 0) { while(nanswers > 0) {
/* The first byte in the answer resource record determines if it /* 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) { if(*nameptr & 0xc0) {
/* Compressed name. */ /* Compressed name. */
nameptr +=2; nameptr +=2;
/* printf("Compressed anwser\n");*/ /* printf("Compressed anwser\n");*/
} else { } else {
/* Not compressed name. */ /* Not compressed name. */
nameptr = parse_name((char *)nameptr); nameptr = parse_name(nameptr);
} }
ans = (struct dns_answer *)nameptr; ans = (struct dns_answer *)nameptr;
/* printf("Answer: type %x, class %x, ttl %x, length %x\n", /* printf("Answer: type %x, class %x, ttl %x, length %x\n",
htons(ans->type), htons(ans->class), (htons(ans->ttl[0]) htons(ans->type), htons(ans->class), (htons(ans->ttl[0])
<< 16) | htons(ans->ttl[1]), htons(ans->len));*/ << 16) | htons(ans->ttl[1]), htons(ans->len));*/
/* Check for IP address type and Internet class. Others are /* Check for IP address type and Internet class. Others are
discarded. */ discarded. */
if(ans->type == HTONS(1) && if(ans->type == HTONS(1) &&
ans->class == HTONS(1) && ans->class == HTONS(1) &&
ans->len == HTONS(4)) { ans->len == HTONS(4)) {
/* printf("IP address %d.%d.%d.%d\n", /* printf("IP address %d.%d.%d.%d\n",
htons(ans->ipaddr[0]) >> 8, htons(ans->ipaddr[0]) >> 8,
htons(ans->ipaddr[0]) & 0xff, htons(ans->ipaddr[0]) & 0xff,
htons(ans->ipaddr[1]) >> 8, htons(ans->ipaddr[1]) >> 8,
htons(ans->ipaddr[1]) & 0xff);*/ htons(ans->ipaddr[1]) & 0xff);*/
/* XXX: we should really check that this IP address is the one /* XXX: we should really check that this IP address is the one
we want. */ we want. */
namemapptr->ipaddr[0] = ans->ipaddr[0]; namemapptr->ipaddr[0] = ans->ipaddr[0];
namemapptr->ipaddr[1] = ans->ipaddr[1]; namemapptr->ipaddr[1] = ans->ipaddr[1];
resolv_found(namemapptr->name, namemapptr->ipaddr); resolv_found(namemapptr->name, namemapptr->ipaddr);
return; return;
} else { } else {
nameptr = nameptr + 10 + htons(ans->len); nameptr = nameptr + 10 + htons(ans->len);
} }
--nanswers; --nanswers;
} }

View File

@ -331,7 +331,7 @@ find_netif(void)
/* Walk through every network interface to check for a match. */ /* Walk through every network interface to check for a match. */
for(netif = netifs; netif != NULL; netif = netif->next) { for(netif = netifs; netif != NULL; netif = netif->next) {
if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr, if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
netif->netmask)) { netif->netmask)) {
/* If there was a match, we break the loop. */ /* If there was a match, we break the loop. */
return netif; return netif;
} }
@ -385,8 +385,8 @@ uip_fw_output(void)
netif = find_netif(); netif = find_netif();
/* printf("uip_fw_output: netif %p ->output %p len %d\n", netif, /* printf("uip_fw_output: netif %p ->output %p len %d\n", netif,
netif->output, netif->output,
uip_len);*/ uip_len);*/
if(netif == NULL) { if(netif == NULL) {
return UIP_FW_NOROUTE; return UIP_FW_NOROUTE;

View File

@ -53,12 +53,12 @@
*/ */
struct uip_fw_netif { struct uip_fw_netif {
struct uip_fw_netif *next; /**< Pointer to the next interface when 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 ipaddr[2]; /**< The IP address of this interface. */
u16_t netmask[2]; /**< The netmask of the interface. */ u16_t netmask[2]; /**< The netmask of the interface. */
u8_t (* output)(void); u8_t (* output)(void);
/**< A pointer to the function that /**< 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) \ #define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \
NULL, \ NULL, \
{HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \ {HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \
{HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \ {HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \
outputfunc outputfunc
/** /**

View File

@ -91,8 +91,8 @@ uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr)
u8_t oldest_time; u8_t oldest_time;
/*printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", /*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[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
addr->addr.addr[4], addr->addr.addr[5]);*/ addr->addr.addr[4], addr->addr.addr[5]);*/
/* Find the first unused entry or the oldest used entry. */ /* Find the first unused entry or the oldest used entry. */
oldest_time = 0; oldest_time = 0;
@ -151,8 +151,8 @@ uip_neighbor_lookup(uip_ipaddr_t ipaddr)
e = find_entry(ipaddr); e = find_entry(ipaddr);
if(e != NULL) { if(e != NULL) {
/* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", /* 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[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[4], e->addr.addr.addr[5]);*/
return &e->addr; return &e->addr;
} }

View File

@ -129,52 +129,51 @@ static const uip_ipaddr_t all_zeroes_addr =
#if UIP_FIXEDETHADDR #if UIP_FIXEDETHADDR
const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
UIP_ETHADDR1, UIP_ETHADDR1,
UIP_ETHADDR2, UIP_ETHADDR2,
UIP_ETHADDR3, UIP_ETHADDR3,
UIP_ETHADDR4, UIP_ETHADDR4,
UIP_ETHADDR5}}; UIP_ETHADDR5}};
#else #else
struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
#endif #endif
#ifndef UIP_CONF_EXTERNAL_BUFFER #ifndef UIP_CONF_EXTERNAL_BUFFER
u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
incoming packets. */ incoming packets. */
#endif /* UIP_CONF_EXTERNAL_BUFFER */ #endif /* UIP_CONF_EXTERNAL_BUFFER */
void *uip_appdata; /* The uip_appdata pointer points to void *uip_appdata; /* The uip_appdata pointer points to
application data. */ application data. */
void *uip_sappdata; /* The uip_appdata pointer points to void *uip_sappdata; /* The uip_appdata pointer points to
the application data which is to the application data which is to
be sent. */ be sent. */
#if UIP_URGDATA > 0 #if UIP_URGDATA > 0
void *uip_urgdata; /* The uip_urgdata pointer points to void *uip_urgdata; /* The uip_urgdata pointer points to
urgent data (out-of-band data), if urgent data (out-of-band data), if
present. */ present. */
u16_t uip_urglen, uip_surglen; u16_t uip_urglen, uip_surglen;
#endif /* UIP_URGDATA > 0 */ #endif /* UIP_URGDATA > 0 */
u16_t uip_len, uip_slen; u16_t uip_len, uip_slen; /* The uip_len is either 8 or 16 bits,
/* The uip_len is either 8 or 16 bits, depending on the maximum packet
depending on the maximum packet size. */
size. */
u8_t uip_flags; /* The uip_flags variable is used for u8_t uip_flags; /* The uip_flags variable is used for
communication between the TCP/IP stack communication between the TCP/IP stack
and the application program. */ and the application program. */
#if UIP_TCP #if UIP_TCP
struct uip_conn *uip_conn; /* uip_conn always points to the current struct uip_conn *uip_conn; /* uip_conn always points to the current
connection. */ connection. */
struct uip_conn uip_conns[UIP_CONNS]; struct uip_conn uip_conns[UIP_CONNS];
/* The uip_conns array holds all TCP /* The uip_conns array holds all TCP
connections. */ connections. */
u16_t uip_listenports[UIP_LISTENPORTS]; u16_t uip_listenports[UIP_LISTENPORTS];
/* The uip_listenports list all currently /* 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 u8_t uip_forced_poll; // 1 if forcing the polling, 0 if the polling is not forced
#endif /* UIP_TCP */ #endif /* UIP_TCP */
@ -184,19 +183,19 @@ struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
#endif /* UIP_UDP */ #endif /* UIP_UDP */
static u16_t ipid; /* Ths ipid variable is an increasing static u16_t ipid; /* Ths ipid variable is an increasing
number that is used for the IP ID number that is used for the IP ID
field. */ field. */
void uip_setipid(u16_t id) { ipid = id; } void uip_setipid(u16_t id) { ipid = id; }
#if UIP_TCP #if UIP_TCP
static u8_t iss[4]; /* The iss variable is used for the TCP static u8_t iss[4]; /* The iss variable is used for the TCP
initial sequence number. */ initial sequence number. */
#endif /* UIP_TCP */ #endif /* UIP_TCP */
#if UIP_ACTIVE_OPEN #if UIP_ACTIVE_OPEN
static u16_t lastport; /* Keeps track of the last port used for static u16_t lastport; /* Keeps track of the last port used for
a new connection. */ a new connection. */
#endif /* UIP_ACTIVE_OPEN */ #endif /* UIP_ACTIVE_OPEN */
/* Temporary variables. */ /* Temporary variables. */
@ -290,7 +289,7 @@ uip_add32(u8_t *op32, u16_t op16)
if(uip_acc32[2] == 0) { if(uip_acc32[2] == 0) {
++uip_acc32[1]; ++uip_acc32[1];
if(uip_acc32[1] == 0) { 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; dataptr = data;
last_byte = data + len - 1; 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]; t = (dataptr[0] << 8) + dataptr[1];
sum += t; sum += t;
if(sum < t) { if(sum < t) {
sum++; /* carry */ sum++; /* carry */
} }
dataptr += 2; dataptr += 2;
} }
@ -323,7 +322,7 @@ chksum(u16_t sum, const u8_t *data, u16_t len)
t = (dataptr[0] << 8) + 0; t = (dataptr[0] << 8) + 0;
sum += t; sum += t;
if(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 TCP header and data. */
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
upper_layer_len); upper_layer_len);
return (sum == 0) ? 0xffff : htons(sum); 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(cconn->tcpstateflags == UIP_TIME_WAIT) {
if(conn == 0 || if(conn == 0 ||
cconn->timer > conn->timer) { cconn->timer > conn->timer) {
conn = cconn; conn = cconn;
} }
} }
} }
@ -606,7 +605,7 @@ uip_listen(u16_t port)
static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, 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 u16_t uip_reasslen;
static u8_t uip_reassflags; static u8_t uip_reassflags;
#define UIP_REASS_FLAG_LASTFRAG 0x01 #define UIP_REASS_FLAG_LASTFRAG 0x01
@ -655,28 +654,28 @@ uip_reass(void)
/* Copy the fragment into the reassembly buffer, at the right /* Copy the fragment into the reassembly buffer, at the right
offset. */ offset. */
memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
(char *)BUF + (int)((BUF->vhl & 0x0f) * 4), (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
len); len);
/* Update the bitmap. */ /* Update the bitmap. */
if(offset / (8 * 8) == (offset + len) / (8 * 8)) { if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
/* If the two endpoints are in the same byte, we only update /* If the two endpoints are in the same byte, we only update
that byte. */ that byte. */
uip_reassbitmap[offset / (8 * 8)] |= uip_reassbitmap[offset / (8 * 8)] |=
bitmap_bits[(offset / 8 ) & 7] & bitmap_bits[(offset / 8 ) & 7] &
~bitmap_bits[((offset + len) / 8 ) & 7]; ~bitmap_bits[((offset + len) / 8 ) & 7];
} else { } else {
/* If the two endpoints are in different bytes, we update the /* If the two endpoints are in different bytes, we update the
bytes in the endpoints and fill the stuff inbetween with bytes in the endpoints and fill the stuff inbetween with
0xff. */ 0xff. */
uip_reassbitmap[offset / (8 * 8)] |= 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) { 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)] |= 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 /* If this fragment has the More Fragments flag set to zero, we
@ -695,27 +694,27 @@ uip_reass(void)
in the bitmap are set. */ in the bitmap are set. */
if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
/* Check all bytes up to and including all but the last byte in /* 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) { for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
if(uip_reassbitmap[i] != 0xff) { if(uip_reassbitmap[i] != 0xff) {
goto nullreturn; goto nullreturn;
} }
} }
/* Check the last byte in the bitmap. It should contain just the /* 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)] != if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
(u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
goto nullreturn; goto nullreturn;
} }
/* If we have come this far, we have a full packet in the /* 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 buffer, so we allocate a pbuf and copy the packet into it. We
also reset the timer. */ also reset the timer. */
uip_reasstmr = 0; uip_reasstmr = 0;
memcpy(BUF, FBUF, uip_reasslen); memcpy(BUF, FBUF, uip_reasslen);
/* Pretend to be a "normal" (i.e., not fragmented) IP packet /* 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->ipoffset[0] = BUF->ipoffset[1] = 0;
BUF->len[0] = uip_reasslen >> 8; BUF->len[0] = uip_reasslen >> 8;
BUF->len[1] = uip_reasslen & 0xff; BUF->len[1] = uip_reasslen & 0xff;
@ -764,9 +763,10 @@ uip_process(u8_t flag)
if(flag == UIP_POLL_REQUEST) { if(flag == UIP_POLL_REQUEST) {
if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
!uip_outstanding(uip_connr)) { !uip_outstanding(uip_connr)) {
uip_flags = UIP_POLL; uip_flags = UIP_POLL;
UIP_APPCALL(); uip_len = uip_slen = 0;
goto appsend; UIP_APPCALL();
goto appsend;
} }
goto drop; goto drop;
@ -780,9 +780,9 @@ uip_process(u8_t flag)
/* Increase the initial sequence number. */ /* Increase the initial sequence number. */
if(++iss[3] == 0) { if(++iss[3] == 0) {
if(++iss[2] == 0) { if(++iss[2] == 0) {
if(++iss[1] == 0) { if(++iss[1] == 0) {
++iss[0]; ++iss[0];
} }
} }
} }
@ -798,80 +798,80 @@ uip_process(u8_t flag)
uip_connr->tcpstateflags == UIP_FIN_WAIT_2)) { uip_connr->tcpstateflags == UIP_FIN_WAIT_2)) {
++(uip_connr->timer); ++(uip_connr->timer);
if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { 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) { } else if(uip_connr->tcpstateflags != UIP_CLOSED && uip_connr->tcpstateflags != UIP_RESERVED) {
/* If the connection has outstanding data, we increase the /* If the connection has outstanding data, we increase the
connection's timer and see if it has reached the RTO value connection's timer and see if it has reached the RTO value
in which case we retransmit. */ in which case we retransmit. */
if(uip_outstanding(uip_connr) && !uip_forced_poll) { if(uip_outstanding(uip_connr) && !uip_forced_poll) {
if(uip_connr->timer-- == 0) { if(uip_connr->timer-- == 0) {
if(uip_connr->nrtx == UIP_MAXRTX || if(uip_connr->nrtx == UIP_MAXRTX ||
((uip_connr->tcpstateflags == UIP_SYN_SENT || ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
uip_connr->tcpstateflags == UIP_SYN_RCVD) && uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
uip_connr->nrtx == UIP_MAXSYNRTX)) { uip_connr->nrtx == UIP_MAXSYNRTX)) {
uip_connr->tcpstateflags = UIP_CLOSED; uip_connr->tcpstateflags = UIP_CLOSED;
/* We call UIP_APPCALL() with uip_flags set to /* We call UIP_APPCALL() with uip_flags set to
UIP_TIMEDOUT to inform the application that the UIP_TIMEDOUT to inform the application that the
connection has timed out. */ connection has timed out. */
uip_flags = UIP_TIMEDOUT; uip_flags = UIP_TIMEDOUT;
UIP_APPCALL(); UIP_APPCALL();
/* We also send a reset packet to the remote host. */ /* We also send a reset packet to the remote host. */
BUF->flags = TCP_RST | TCP_ACK; BUF->flags = TCP_RST | TCP_ACK;
goto tcp_send_nodata; goto tcp_send_nodata;
} }
/* Exponential backoff. */ /* Exponential backoff. */
uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
4: 4:
uip_connr->nrtx); uip_connr->nrtx);
++(uip_connr->nrtx); ++(uip_connr->nrtx);
/* Ok, so we need to retransmit. We do this differently /* Ok, so we need to retransmit. We do this differently
depending on which state we are in. In ESTABLISHED, we depending on which state we are in. In ESTABLISHED, we
call upon the application so that it may prepare the call upon the application so that it may prepare the
data for the retransmit. In SYN_RCVD, we resend the data for the retransmit. In SYN_RCVD, we resend the
SYNACK that we sent earlier and in LAST_ACK we have to SYNACK that we sent earlier and in LAST_ACK we have to
retransmit our FINACK. */ retransmit our FINACK. */
UIP_STAT(++uip_stat.tcp.rexmit); UIP_STAT(++uip_stat.tcp.rexmit);
switch(uip_connr->tcpstateflags & UIP_TS_MASK) { switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
case UIP_SYN_RCVD: case UIP_SYN_RCVD:
/* In the SYN_RCVD state, we should retransmit our /* In the SYN_RCVD state, we should retransmit our
SYNACK. */ SYNACK. */
goto tcp_send_synack; goto tcp_send_synack;
#if UIP_ACTIVE_OPEN #if UIP_ACTIVE_OPEN
case UIP_SYN_SENT: case UIP_SYN_SENT:
/* In the SYN_SENT state, we retransmit out SYN. */ /* In the SYN_SENT state, we retransmit out SYN. */
BUF->flags = 0; BUF->flags = 0;
goto tcp_send_syn; goto tcp_send_syn;
#endif /* UIP_ACTIVE_OPEN */ #endif /* UIP_ACTIVE_OPEN */
case UIP_ESTABLISHED: case UIP_ESTABLISHED:
/* In the ESTABLISHED state, we call upon the application /* In the ESTABLISHED state, we call upon the application
to do the actual retransmit after which we jump into to do the actual retransmit after which we jump into
the code for sending out the packet (the apprexmit the code for sending out the packet (the apprexmit
label). */ label). */
uip_flags = UIP_REXMIT; uip_flags = UIP_REXMIT;
UIP_APPCALL(); UIP_APPCALL();
goto apprexmit; goto apprexmit;
case UIP_FIN_WAIT_1: case UIP_FIN_WAIT_1:
case UIP_CLOSING: case UIP_CLOSING:
case UIP_LAST_ACK: case UIP_LAST_ACK:
/* In all these states we should retransmit a FINACK. */ /* In all these states we should retransmit a FINACK. */
goto tcp_send_finack; goto tcp_send_finack;
} }
} }
} else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { } 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. */ application for new data. */
uip_flags = UIP_POLL; uip_flags = UIP_POLL;
UIP_APPCALL(); UIP_APPCALL();
goto appsend; goto appsend;
} }
} }
goto drop; goto drop;
@ -928,14 +928,14 @@ uip_process(u8_t flag)
uip_len = (BUF->len[0] << 8) + BUF->len[1]; uip_len = (BUF->len[0] << 8) + BUF->len[1];
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6
uip_len += 40; /* The length reported in the IPv6 header is the uip_len += 40; /* The length reported in the IPv6 header is the
length of the payload that follows the length of the payload that follows the
header. However, uIP uses the uip_len variable header. However, uIP uses the uip_len variable
for holding the size of the entire packet, for holding the size of the entire packet,
including the IP header. For IPv4 this is not a including the IP header. For IPv4 this is not a
problem as the length field in the IPv4 header problem as the length field in the IPv4 header
contains the length of the entire packet. But contains the length of the entire packet. But
for IPv6 we need to add the size of the IPv6 for IPv6 we need to add the size of the IPv6
header (40 bytes). */ header (40 bytes). */
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */
} else { } else {
UIP_LOG("ip: packet shorter than reported in IP header."); 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 && if(BUF->proto == UIP_PROTO_UDP &&
uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
/*&& /*&&
uip_ipchksum() == 0xffff*/) { uip_ipchksum() == 0xffff*/) {
goto udp_input; goto udp_input;
} }
#endif /* UIP_BROADCAST */ #endif /* UIP_BROADCAST */
@ -1009,7 +1009,7 @@ uip_process(u8_t flag)
#if !UIP_CONF_IPV6 #if !UIP_CONF_IPV6
if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
checksum. */ checksum. */
UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.drop);
UIP_STAT(++uip_stat.ip.chkerr); UIP_STAT(++uip_stat.ip.chkerr);
UIP_LOG("ip: bad checksum."); UIP_LOG("ip: bad checksum.");
@ -1019,8 +1019,8 @@ uip_process(u8_t flag)
#if UIP_TCP #if UIP_TCP
if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so, if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
proceed with TCP input proceed with TCP input
processing. */ processing. */
goto tcp_input; goto tcp_input;
} }
#endif /* UIP_TCP */ #endif /* UIP_TCP */
@ -1034,7 +1034,7 @@ uip_process(u8_t flag)
#if !UIP_CONF_IPV6 #if !UIP_CONF_IPV6
/* ICMPv4 processing code follows. */ /* ICMPv4 processing code follows. */
if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from 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.drop);
UIP_STAT(++uip_stat.ip.protoerr); UIP_STAT(++uip_stat.ip.protoerr);
UIP_LOG("ip: neither tcp nor icmp."); 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); DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from 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.drop);
UIP_STAT(++uip_stat.ip.protoerr); UIP_STAT(++uip_stat.ip.protoerr);
UIP_LOG("ip: neither tcp nor icmp6."); 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(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) { if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
/* Save the sender's address in our neighbor list. */ /* Save the sender's address in our neighbor list. */
uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
} }
/* We should now send a neighbor advertisement back to where the /* 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->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
@ -1188,8 +1188,8 @@ uip_process(u8_t flag)
UDPBUF->srcport == uip_udp_conn->rport || UDPBUF->srcport == uip_udp_conn->rport ||
uip_udp_conn->rport == HTONS(69)) && uip_udp_conn->rport == HTONS(69)) &&
(uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) || (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) { uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
goto udp_found; goto udp_found;
} }
} }
@ -1197,6 +1197,7 @@ uip_process(u8_t flag)
goto drop; goto drop;
udp_found: udp_found:
UIP_STAT(++uip_stat.udp.recv);
#if UIP_TCP #if UIP_TCP
uip_conn = NULL; uip_conn = NULL;
#endif /* UIP_TCP */ #endif /* UIP_TCP */
@ -1232,7 +1233,7 @@ uip_process(u8_t flag)
uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr); 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 #if UIP_UDP_CHECKSUMS
/* Calculate UDP checksum. */ /* Calculate UDP checksum. */
@ -1242,6 +1243,7 @@ uip_process(u8_t flag)
} }
#endif /* UIP_UDP_CHECKSUMS */ #endif /* UIP_UDP_CHECKSUMS */
UIP_STAT(++uip_stat.udp.sent);
goto ip_send_nolen; goto ip_send_nolen;
#endif /* UIP_UDP */ #endif /* UIP_UDP */
@ -1253,7 +1255,7 @@ uip_process(u8_t flag)
/* Start of TCP input header processing code. */ /* Start of TCP input header processing code. */
if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
checksum. */ checksum. */
UIP_STAT(++uip_stat.tcp.drop); UIP_STAT(++uip_stat.tcp.drop);
UIP_STAT(++uip_stat.tcp.chkerr); UIP_STAT(++uip_stat.tcp.chkerr);
UIP_LOG("tcp: bad checksum."); UIP_LOG("tcp: bad checksum.");
@ -1269,6 +1271,10 @@ uip_process(u8_t flag)
BUF->destport == uip_connr->lport && BUF->destport == uip_connr->lport &&
BUF->srcport == uip_connr->rport && BUF->srcport == uip_connr->rport &&
uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) { 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; goto found;
} }
} }
@ -1326,7 +1332,7 @@ uip_process(u8_t flag)
if(++BUF->ackno[3] == 0) { if(++BUF->ackno[3] == 0) {
if(++BUF->ackno[2] == 0) { if(++BUF->ackno[2] == 0) {
if(++BUF->ackno[1] == 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_conns[c].tcpstateflags == UIP_TIME_WAIT) {
if(uip_connr == 0 || if(uip_connr == 0 ||
uip_conns[c].timer > uip_connr->timer) { uip_conns[c].timer > uip_connr->timer) {
uip_connr = &uip_conns[c]; uip_connr = &uip_conns[c];
} }
} }
} }
@ -1405,30 +1411,30 @@ uip_process(u8_t flag)
for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
if(opt == TCP_OPT_END) { if(opt == TCP_OPT_END) {
/* End of options. */ /* End of options. */
break; break;
} else if(opt == TCP_OPT_NOOP) { } else if(opt == TCP_OPT_NOOP) {
++c; ++c;
/* NOP option. */ /* NOP option. */
} else if(opt == TCP_OPT_MSS && } else if(opt == TCP_OPT_MSS &&
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
/* An MSS option with the right option length. */ /* An MSS option with the right option length. */
tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | 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]; (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
uip_connr->initialmss = uip_connr->mss = uip_connr->initialmss = uip_connr->mss =
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
/* And we are done processing options. */ /* And we are done processing options. */
break; break;
} else { } else {
/* All other options have a length field, so that we easily /* All other options have a length field, so that we easily
can skip past them. */ can skip past them. */
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
/* If the length field is zero, the options are malformed /* If the length field is zero, the options are malformed
and we don't process them further. */ and we don't process them further. */
break; break;
} }
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; 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 /* 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 what we're expecting next. If not, we send out an ACK with the
correct numbers in. */ correct numbers in, unless we are in the SYN_RCVD state and
if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && receive a SYN, in which case we should retransmit our SYNACK
((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) { (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)) && if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
(BUF->seqno[0] != uip_connr->rcv_nxt[0] || (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
BUF->seqno[1] != uip_connr->rcv_nxt[1] || BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
BUF->seqno[2] != uip_connr->rcv_nxt[2] || BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
BUF->seqno[3] != uip_connr->rcv_nxt[3])) { BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
goto tcp_send_ack; 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[1] = uip_acc32[1];
uip_connr->snd_nxt[2] = uip_acc32[2]; uip_connr->snd_nxt[2] = uip_acc32[2];
uip_connr->snd_nxt[3] = uip_acc32[3]; uip_connr->snd_nxt[3] = uip_acc32[3];
/* Do RTT estimation, unless we have done retransmissions. */ /* Do RTT estimation, unless we have done retransmissions. */
if(uip_connr->nrtx == 0) { if(uip_connr->nrtx == 0) {
signed char m; signed char m;
m = uip_connr->rto - uip_connr->timer; m = uip_connr->rto - uip_connr->timer;
/* This is taken directly from VJs original code in his paper */ /* This is taken directly from VJs original code in his paper */
m = m - (uip_connr->sa >> 3); m = m - (uip_connr->sa >> 3);
uip_connr->sa += m; uip_connr->sa += m;
if(m < 0) { if(m < 0) {
m = -m; m = -m;
} }
m = m - (uip_connr->sv >> 2); m = m - (uip_connr->sv >> 2);
uip_connr->sv += m; uip_connr->sv += m;
uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
} }
/* Set the acknowledged flag. */ /* Set the acknowledged flag. */
@ -1539,9 +1549,9 @@ uip_process(u8_t flag)
/* Do different things depending on in what state the connection is. */ /* Do different things depending on in what state the connection is. */
switch(uip_connr->tcpstateflags & UIP_TS_MASK) { switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
/* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
implemented, since we force the application to close when the implemented, since we force the application to close when the
peer sends a FIN (hence the application goes directly from peer sends a FIN (hence the application goes directly from
ESTABLISHED to LAST_ACK). */ ESTABLISHED to LAST_ACK). */
case UIP_SYN_RCVD: case UIP_SYN_RCVD:
/* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and /* 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 we are waiting for an ACK that acknowledges the data we sent
@ -1559,6 +1569,10 @@ uip_process(u8_t flag)
UIP_APPCALL(); UIP_APPCALL();
goto appsend; goto appsend;
} }
/* We need to retransmit the SYNACK */
if((BUF->flags & TCP_CTL) == TCP_SYN) {
goto tcp_send_synack;
}
goto drop; goto drop;
#if UIP_ACTIVE_OPEN #if UIP_ACTIVE_OPEN
case UIP_SYN_SENT: case UIP_SYN_SENT:
@ -1571,35 +1585,35 @@ uip_process(u8_t flag)
/* Parse the TCP MSS option, if present. */ /* Parse the TCP MSS option, if present. */
if((BUF->tcpoffset & 0xf0) > 0x50) { if((BUF->tcpoffset & 0xf0) > 0x50) {
for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
if(opt == TCP_OPT_END) { if(opt == TCP_OPT_END) {
/* End of options. */ /* End of options. */
break; break;
} else if(opt == TCP_OPT_NOOP) { } else if(opt == TCP_OPT_NOOP) {
++c; ++c;
/* NOP option. */ /* NOP option. */
} else if(opt == TCP_OPT_MSS && } else if(opt == TCP_OPT_MSS &&
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
/* An MSS option with the right option length. */ /* An MSS option with the right option length. */
tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
uip_connr->initialmss = uip_connr->initialmss =
uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
/* And we are done processing options. */ /* And we are done processing options. */
break; break;
} else { } else {
/* All other options have a length field, so that we easily /* All other options have a length field, so that we easily
can skip past them. */ can skip past them. */
if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
/* If the length field is zero, the options are malformed /* If the length field is zero, the options are malformed
and we don't process them further. */ and we don't process them further. */
break; break;
} }
c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
} }
} }
} }
uip_connr->tcpstateflags = UIP_ESTABLISHED; uip_connr->tcpstateflags = UIP_ESTABLISHED;
uip_connr->rcv_nxt[0] = BUF->seqno[0]; 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(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
if(uip_outstanding(uip_connr)) { if(uip_outstanding(uip_connr)) {
goto drop; goto drop;
} }
uip_add_rcv_nxt(1 + uip_len); uip_add_rcv_nxt(1 + uip_len);
uip_flags |= UIP_CLOSE; uip_flags |= UIP_CLOSE;
if(uip_len > 0) { if(uip_len > 0) {
uip_flags |= UIP_NEWDATA; uip_flags |= UIP_NEWDATA;
} }
UIP_APPCALL(); UIP_APPCALL();
uip_connr->len = 1; uip_connr->len = 1;
@ -1658,8 +1672,8 @@ uip_process(u8_t flag)
#if UIP_URGDATA > 0 #if UIP_URGDATA > 0
uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
if(uip_urglen > uip_len) { if(uip_urglen > uip_len) {
/* There is more urgent data in the next segment to come. */ /* There is more urgent data in the next segment to come. */
uip_urglen = uip_len; uip_urglen = uip_len;
} }
uip_add_rcv_nxt(uip_urglen); uip_add_rcv_nxt(uip_urglen);
uip_len -= uip_urglen; uip_len -= uip_urglen;
@ -1725,52 +1739,52 @@ uip_process(u8_t flag)
appsend: appsend:
if(uip_flags & UIP_ABORT) { if(uip_flags & UIP_ABORT) {
uip_slen = 0; uip_slen = 0;
uip_connr->tcpstateflags = UIP_CLOSED; uip_connr->tcpstateflags = UIP_CLOSED;
BUF->flags = TCP_RST | TCP_ACK; BUF->flags = TCP_RST | TCP_ACK;
goto tcp_send_nodata; goto tcp_send_nodata;
} }
if(uip_flags & UIP_CLOSE) { if(uip_flags & UIP_CLOSE) {
uip_slen = 0; uip_slen = 0;
uip_connr->len = 1; uip_connr->len = 1;
uip_connr->tcpstateflags = UIP_FIN_WAIT_1; uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
uip_connr->nrtx = 0; uip_connr->nrtx = 0;
BUF->flags = TCP_FIN | TCP_ACK; BUF->flags = TCP_FIN | TCP_ACK;
goto tcp_send_nodata; goto tcp_send_nodata;
} }
/* If uip_slen > 0, the application has data to be sent. */ /* If uip_slen > 0, the application has data to be sent. */
if(uip_slen > 0) { if(uip_slen > 0) {
/* If the connection has acknowledged data, the contents of /* If the connection has acknowledged data, the contents of
the ->len variable should be discarded. */ the ->len variable should be discarded. */
if((uip_flags & UIP_ACKDATA) != 0) { if((uip_flags & UIP_ACKDATA) != 0) {
uip_connr->len = 0; uip_connr->len = 0;
} }
/* If the ->len variable is non-zero the connection has /* If the ->len variable is non-zero the connection has
already data in transit and cannot send anymore right already data in transit and cannot send anymore right
now. */ now. */
if(uip_connr->len == 0) { if(uip_connr->len == 0) {
/* The application cannot send more than what is allowed by /* The application cannot send more than what is allowed by
the mss (the minumum of the MSS and the available the mss (the minumum of the MSS and the available
window). */ window). */
if(uip_slen > uip_connr->mss) { if(uip_slen > uip_connr->mss) {
uip_slen = uip_connr->mss; uip_slen = uip_connr->mss;
} }
/* Remember how much data we send out now so that we know /* Remember how much data we send out now so that we know
when everything has been acknowledged. */ when everything has been acknowledged. */
uip_connr->len = uip_slen; uip_connr->len = uip_slen;
} else { } else {
/* If the application already had unacknowledged data, we /* If the application already had unacknowledged data, we
make sure that the application does not send (i.e., make sure that the application does not send (i.e.,
retransmit) out more than it previously sent out. */ retransmit) out more than it previously sent out. */
uip_slen = uip_connr->len; uip_slen = uip_connr->len;
} }
} }
uip_connr->nrtx = 0; uip_connr->nrtx = 0;
apprexmit: apprexmit:
@ -1779,19 +1793,19 @@ uip_process(u8_t flag)
/* If the application has data to be sent, or if the incoming /* If the application has data to be sent, or if the incoming
packet had new data in it, we must send out a packet. */ packet had new data in it, we must send out a packet. */
if(uip_slen > 0 && uip_connr->len > 0) { if(uip_slen > 0 && uip_connr->len > 0) {
/* Add the length of the IP and TCP headers. */ /* Add the length of the IP and TCP headers. */
uip_len = uip_connr->len + UIP_TCPIP_HLEN; uip_len = uip_connr->len + UIP_TCPIP_HLEN;
/* We always set the ACK flag in response packets. */ /* We always set the ACK flag in response packets. */
BUF->flags = TCP_ACK | TCP_PSH; BUF->flags = TCP_ACK | TCP_PSH;
/* Send the packet. */ /* Send the packet. */
goto tcp_send_noopts; goto tcp_send_noopts;
} }
/* If there is no data to send, just send out a pure ACK if /* 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) { if(uip_flags & UIP_NEWDATA) {
uip_len = UIP_TCPIP_HLEN; uip_len = UIP_TCPIP_HLEN;
BUF->flags = TCP_ACK; BUF->flags = TCP_ACK;
goto tcp_send_noopts; goto tcp_send_noopts;
} }
} }
goto drop; goto drop;
@ -1814,11 +1828,11 @@ uip_process(u8_t flag)
} }
if(BUF->flags & TCP_FIN) { if(BUF->flags & TCP_FIN) {
if(uip_flags & UIP_ACKDATA) { if(uip_flags & UIP_ACKDATA) {
uip_connr->tcpstateflags = UIP_TIME_WAIT; uip_connr->tcpstateflags = UIP_TIME_WAIT;
uip_connr->timer = 0; uip_connr->timer = 0;
uip_connr->len = 0; uip_connr->len = 0;
} else { } else {
uip_connr->tcpstateflags = UIP_CLOSING; uip_connr->tcpstateflags = UIP_CLOSING;
} }
uip_add_rcv_nxt(1); uip_add_rcv_nxt(1);
uip_flags = UIP_CLOSE; uip_flags = UIP_CLOSE;
@ -1944,7 +1958,7 @@ uip_process(u8_t flag)
UIP_STAT(++uip_stat.tcp.sent); UIP_STAT(++uip_stat.tcp.sent);
send: send:
DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len, 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); UIP_STAT(++uip_stat.ip.sent);
/* Return and let the caller do the actual transmission. */ /* Return and let the caller do the actual transmission. */

View File

@ -242,12 +242,12 @@ void uip_setipid(u16_t id);
uip_input(); uip_input();
if(uip_len > 0) { if(uip_len > 0) {
uip_arp_out(); uip_arp_out();
ethernet_devicedriver_send(); ethernet_devicedriver_send();
} }
} else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
uip_arp_arpin(); uip_arp_arpin();
if(uip_len > 0) { if(uip_len > 0) {
ethernet_devicedriver_send(); ethernet_devicedriver_send();
} }
} }
\endcode \endcode
@ -926,7 +926,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*/ */
#if !UIP_CONF_IPV6 #if !UIP_CONF_IPV6
#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \ #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 */ #else /* !UIP_CONF_IPV6 */
#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) #define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
#endif /* !UIP_CONF_IPV6 */ #endif /* !UIP_CONF_IPV6 */
@ -1173,26 +1173,26 @@ struct uip_conn {
u16_t lport; /**< The local TCP port, in network byte order. */ u16_t lport; /**< The local TCP port, in network byte order. */
u16_t rport; /**< The local remote TCP port, in network byte 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 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 u8_t snd_nxt[4]; /**< The sequence number that was last sent by
us. */ us. */
u16_t len; /**< Length of the data that was previously sent. */ u16_t len; /**< Length of the data that was previously sent. */
u16_t mss; /**< Current maximum segment size for the u16_t mss; /**< Current maximum segment size for the
connection. */ connection. */
u16_t initialmss; /**< Initial maximum segment size for the u16_t initialmss; /**< Initial maximum segment size for the
connection. */ connection. */
u8_t sa; /**< Retransmission time-out calculation state u8_t sa; /**< Retransmission time-out calculation state
variable. */ variable. */
u8_t sv; /**< Retransmission time-out calculation state u8_t sv; /**< Retransmission time-out calculation state
variable. */ variable. */
u8_t rto; /**< Retransmission time-out. */ u8_t rto; /**< Retransmission time-out. */
u8_t tcpstateflags; /**< TCP state and flags. */ u8_t tcpstateflags; /**< TCP state and flags. */
u8_t timer; /**< The retransmission timer. */ u8_t timer; /**< The retransmission timer. */
u8_t nrtx; /**< The number of retransmissions for the last u8_t nrtx; /**< The number of retransmissions for the last
segment sent. */ segment sent. */
/** The application state. */ /** The application state. */
uip_tcp_appstate_t appstate; 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 {
struct { struct {
uip_stats_t drop; /**< Number of dropped packets at the IP uip_stats_t drop; /**< Number of dropped packets at the IP
layer. */ layer. */
uip_stats_t recv; /**< Number of received packets at the IP uip_stats_t recv; /**< Number of received packets at the IP
layer. */ layer. */
uip_stats_t sent; /**< Number of sent packets at the IP uip_stats_t sent; /**< Number of sent packets at the IP
layer. */ layer. */
uip_stats_t vhlerr; /**< Number of packets dropped due to wrong 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 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 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 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 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 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. */ } ip; /**< IP statistics. */
struct { struct {
uip_stats_t drop; /**< Number of dropped ICMP packets. */ uip_stats_t drop; /**< Number of dropped ICMP packets. */
uip_stats_t recv; /**< Number of received ICMP packets. */ uip_stats_t recv; /**< Number of received ICMP packets. */
uip_stats_t sent; /**< Number of sent ICMP packets. */ uip_stats_t sent; /**< Number of sent ICMP packets. */
uip_stats_t typeerr; /**< Number of ICMP packets with a wrong uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
type. */ type. */
} icmp; /**< ICMP statistics. */ } icmp; /**< ICMP statistics. */
#if UIP_TCP #if UIP_TCP
struct { struct {
@ -1284,15 +1284,15 @@ struct uip_stats {
uip_stats_t recv; /**< Number of recived TCP segments. */ uip_stats_t recv; /**< Number of recived TCP segments. */
uip_stats_t sent; /**< Number of sent TCP segments. */ uip_stats_t sent; /**< Number of sent TCP segments. */
uip_stats_t chkerr; /**< Number of TCP segments with a bad 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 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 rst; /**< Number of recevied TCP RST (reset) segments. */
uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
uip_stats_t syndrop; /**< Number of dropped SYNs due to too few 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, uip_stats_t synrst; /**< Number of SYNs for closed ports,
triggering a RST. */ triggering a RST. */
} tcp; /**< TCP statistics. */ } tcp; /**< TCP statistics. */
#endif /* UIP_TCP */ #endif /* UIP_TCP */
#if UIP_UDP #if UIP_UDP
@ -1301,7 +1301,7 @@ struct uip_stats {
uip_stats_t recv; /**< Number of recived UDP segments. */ uip_stats_t recv; /**< Number of recived UDP segments. */
uip_stats_t sent; /**< Number of sent UDP segments. */ uip_stats_t sent; /**< Number of sent UDP segments. */
uip_stats_t chkerr; /**< Number of UDP segments with a bad uip_stats_t chkerr; /**< Number of UDP segments with a bad
checksum. */ checksum. */
} udp; /**< UDP statistics. */ } udp; /**< UDP statistics. */
#endif /* UIP_UDP */ #endif /* UIP_UDP */
}; };
@ -1335,33 +1335,33 @@ extern u8_t uip_flags;
functions/macros. */ functions/macros. */
#define UIP_ACKDATA 1 /* Signifies that the outstanding data was #define UIP_ACKDATA 1 /* Signifies that the outstanding data was
acked and the application should send acked and the application should send
out new data instead of retransmitting out new data instead of retransmitting
the last data. */ the last data. */
#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent #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 #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 #define UIP_POLL 8 /* Used for polling the application, to
check if the application has data that check if the application has data that
it wants to send. */ it wants to send. */
#define UIP_CLOSE 16 /* The remote host has closed the #define UIP_CLOSE 16 /* The remote host has closed the
connection, thus the connection has connection, thus the connection has
gone away. Or the application signals gone away. Or the application signals
that it wants to close the that it wants to close the
connection. */ connection. */
#define UIP_ABORT 32 /* The remote host has aborted the #define UIP_ABORT 32 /* The remote host has aborted the
connection, thus the connection has connection, thus the connection has
gone away. Or the application signals gone away. Or the application signals
that it wants to abort the that it wants to abort the
connection. */ connection. */
#define UIP_CONNECTED 64 /* We have got a connection from a remote #define UIP_CONNECTED 64 /* We have got a connection from a remote
host and have set up a new connection host and have set up a new connection
for it, or an active connection has for it, or an active connection has
been successfully established. */ been successfully established. */
#define UIP_TIMEDOUT 128 /* The connection has been aborted due to #define UIP_TIMEDOUT 128 /* The connection has been aborted due to
too many retransmissions. */ too many retransmissions. */
/* uip_process(flag): /* uip_process(flag):
* *
@ -1377,16 +1377,16 @@ void uip_process(u8_t flag);
the macrose defined in this file. */ the macrose defined in this file. */
#define UIP_DATA 1 /* Tells uIP that there is incoming #define UIP_DATA 1 /* Tells uIP that there is incoming
data in the uip_buf buffer. The data in the uip_buf buffer. The
length of the data is stored in the length of the data is stored in the
global variable uip_len. */ global variable uip_len. */
#define UIP_TIMER 2 /* Tells uIP that the periodic timer #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 #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 #define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram
should be constructed in the should be constructed in the
uip_buf buffer. */ uip_buf buffer. */
#if UIP_UDP #if UIP_UDP
#define UIP_UDP_TIMER 5 #define UIP_UDP_TIMER 5
#endif /* UIP_UDP */ #endif /* UIP_UDP */
@ -1544,11 +1544,11 @@ struct uip_udpip_hdr {
#define UIP_UDPH_LEN 8 /* Size of UDP header */ #define UIP_UDPH_LEN 8 /* Size of UDP header */
#define UIP_TCPH_LEN 20 /* Size of TCP header */ #define UIP_TCPH_LEN 20 /* Size of TCP header */
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + #define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP +
UDP UDP
header */ header */
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + #define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP +
TCP TCP
header */ header */
#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN #define UIP_TCPIP_HLEN UIP_IPTCPH_LEN

View File

@ -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 /* Check if the source IP address of the incoming packet matches
the IP address in this ARP table entry. */ the IP address in this ARP table entry. */
if(ipaddr[0] == tabptr->ipaddr[0] && if(ipaddr[0] == tabptr->ipaddr[0] &&
ipaddr[1] == tabptr->ipaddr[1]) { ipaddr[1] == tabptr->ipaddr[1]) {
/* An old entry found, update this and return. */ /* An old entry found, update this and return. */
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
tabptr->time = arptime; 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) { for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i]; tabptr = &arp_table[i];
if(arptime - tabptr->time > tmpage) { if(arptime - tabptr->time > tmpage) {
tmpage = arptime - tabptr->time; tmpage = arptime - tabptr->time;
c = i; c = i;
} }
} }
i = c; i = c;
@ -238,7 +238,7 @@ void
uip_arp_ipin(void) uip_arp_ipin(void)
{ {
uip_len -= sizeof(struct uip_eth_hdr); uip_len -= sizeof(struct uip_eth_hdr);
/* Only insert/update an entry if the source IP address of the /* Only insert/update an entry if the source IP address of the
incoming IP packet comes from a host on the local network. */ incoming IP packet comes from a host on the local network. */
if((IPBUF->srcipaddr[0] & uip_netmask[0]) != if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
@ -293,8 +293,8 @@ uip_arp_arpin(void)
reply. */ reply. */
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
/* First, we register the one who made the request in our ARP /* First, we register the one who made the request in our ARP
table, since it is likely that we will do more communication table, since it is likely that we will do more communication
with this host in the future. */ with this host in the future. */
uip_arp_update(BUF->sipaddr, &BUF->shwaddr); uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
/* The reply opcode is 2. */ /* The reply opcode is 2. */
@ -372,8 +372,8 @@ uip_arp_out(void)
/* Check if the destination address is on the local network. */ /* Check if the destination address is on the local network. */
if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
/* Destination address was not on the local network, so we need to /* Destination address was not on the local network, so we need to
use the default router's IP address instead of the destination use the default router's IP address instead of the destination
address when determining the MAC address. */ address when determining the MAC address. */
uip_ipaddr_copy(ipaddr, uip_draddr); uip_ipaddr_copy(ipaddr, uip_draddr);
} else { } else {
/* Else, we use the destination IP address. */ /* Else, we use the destination IP address. */
@ -383,13 +383,13 @@ uip_arp_out(void)
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i]; tabptr = &arp_table[i];
if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
break; break;
} }
} }
if(i == UIP_ARPTAB_SIZE) { if(i == UIP_ARPTAB_SIZE) {
/* The destination address was not in our ARP table, so we /* 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->ethhdr.dest.addr, 0xff, 6);
memset(BUF->dhwaddr.addr, 0x00, 6); memset(BUF->dhwaddr.addr, 0x00, 6);

View File

@ -57,16 +57,16 @@ uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr)
c = *addrstr; c = *addrstr;
++j; ++j;
if(j > 4) { if(j > 4) {
return 0; return 0;
} }
if(c == '.' || c == 0) { if(c == '.' || c == 0) {
*ipaddr = tmp; *ipaddr = tmp;
++ipaddr; ++ipaddr;
tmp = 0; tmp = 0;
} else if(c >= '0' && c <= '9') { } else if(c >= '0' && c <= '9') {
tmp = (tmp * 10) + (c - '0'); tmp = (tmp * 10) + (c - '0');
} else { } else {
return 0; return 0;
} }
++addrstr; ++addrstr;
} while(c != '.' && c != 0); } while(c != '.' && c != 0);

View File

@ -660,62 +660,35 @@ builder.read_depends = function( self, ftable )
return dtable return dtable
end 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 -- Create and return compile targets for the given sources
builder.create_compile_targets = function( self, ftable, res ) builder.create_compile_targets = function( self, ftable, res )
if type( ftable ) == 'string' then ftable = utils.string_to_table( ftable ) end if type( ftable ) == 'string' then ftable = utils.string_to_table( ftable ) end
res = res or {} res = res or {}
-- Build dependencies for all targets -- Build dependencies for all targets
for i = 1, #ftable do 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 ] ) local deps = self:get_dep_filename( ftable[ i ] )
if ftable[ i ]:find( "%.c$" ) then local target
target = self:c_target( self:obj_name( ftable[ i ] ), { self:get_registered_target( deps ) or ftable[ i ] } ) 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 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 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 ) table.insert( res, target )
end end
return res return res
@ -778,7 +751,6 @@ end
-- Create dependencies, create object files, link final object -- Create dependencies, create object files, link final object
builder.make_exe_target = function( self, target, file_list ) builder.make_exe_target = function( self, target, file_list )
self:make_depends( file_list )
local odeps = self:create_compile_targets( file_list ) local odeps = self:create_compile_targets( file_list )
local exetarget = self:link_target( target, odeps ) local exetarget = self:link_target( target, odeps )
self:default( self:add_target( exetarget ) ) self:default( self:add_target( exetarget ) )